Backed out 3 changesets (bug 1505777) for linux build failures on a CLOSED TREE
authorGurzau Raul <rgurzau@mozilla.com>
Fri, 09 Nov 2018 05:00:08 +0200
changeset 445255 e1450f97acc288c6217152a0efefef1eb1d5108b
parent 445254 8e423aa1c94e3489b7f335b4e039cb5e1b48dbfe
child 445256 1e608b4d239b1b27905a3c93a7bb3b7349232de0
push id109711
push userrgurzau@mozilla.com
push dateFri, 09 Nov 2018 03:01:35 +0000
treeherdermozilla-inbound@1e608b4d239b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1505777
milestone65.0a1
backs outfd3aff6770a58b339f8f6fcf64b466892b5cc110
400c83b3756b97b0e0394e52fb00978d1b64bac9
bbdabbc30f330f5287326d21d1d7331ae731222e
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
Backed out 3 changesets (bug 1505777) for linux build failures on a CLOSED TREE Backed out changeset fd3aff6770a5 (bug 1505777) Backed out changeset 400c83b3756b (bug 1505777) Backed out changeset bbdabbc30f33 (bug 1505777)
Cargo.lock
js/src/wasm/cranelift/Cargo.toml
js/src/wasm/cranelift/src/baldrdash.rs
js/src/wasm/cranelift/src/compile.rs
js/src/wasm/cranelift/src/cpu.rs
js/src/wasm/cranelift/src/wasm2clif.rs
third_party/rust/cranelift-bforest/.cargo-checksum.json
third_party/rust/cranelift-bforest/Cargo.toml
third_party/rust/cranelift-bforest/LICENSE
third_party/rust/cranelift-bforest/src/lib.rs
third_party/rust/cranelift-bforest/src/map.rs
third_party/rust/cranelift-bforest/src/node.rs
third_party/rust/cranelift-bforest/src/path.rs
third_party/rust/cranelift-bforest/src/pool.rs
third_party/rust/cranelift-bforest/src/set.rs
third_party/rust/cranelift-codegen-meta/.cargo-checksum.json
third_party/rust/cranelift-codegen-meta/Cargo.toml
third_party/rust/cranelift-codegen-meta/LICENSE
third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs
third_party/rust/cranelift-codegen-meta/src/cdsl/mod.rs
third_party/rust/cranelift-codegen-meta/src/cdsl/regs.rs
third_party/rust/cranelift-codegen-meta/src/cdsl/types.rs
third_party/rust/cranelift-codegen-meta/src/gen_registers.rs
third_party/rust/cranelift-codegen-meta/src/gen_types.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-meta/src/lib.rs
third_party/rust/cranelift-codegen-meta/src/srcgen.rs
third_party/rust/cranelift-codegen/.cargo-checksum.json
third_party/rust/cranelift-codegen/Cargo.toml
third_party/rust/cranelift-codegen/LICENSE
third_party/rust/cranelift-codegen/build.rs
third_party/rust/cranelift-codegen/meta-python/base/formats.py
third_party/rust/cranelift-codegen/meta-python/base/instructions.py
third_party/rust/cranelift-codegen/meta-python/base/legalize.py
third_party/rust/cranelift-codegen/meta-python/base/settings.py
third_party/rust/cranelift-codegen/meta-python/base/types.py
third_party/rust/cranelift-codegen/meta-python/build.py
third_party/rust/cranelift-codegen/meta-python/cdsl/ast.py
third_party/rust/cranelift-codegen/meta-python/cdsl/instructions.py
third_party/rust/cranelift-codegen/meta-python/cdsl/isa.py
third_party/rust/cranelift-codegen/meta-python/cdsl/predicates.py
third_party/rust/cranelift-codegen/meta-python/cdsl/registers.py
third_party/rust/cranelift-codegen/meta-python/cdsl/test_ti.py
third_party/rust/cranelift-codegen/meta-python/cdsl/ti.py
third_party/rust/cranelift-codegen/meta-python/cdsl/types.py
third_party/rust/cranelift-codegen/meta-python/cdsl/typevar.py
third_party/rust/cranelift-codegen/meta-python/cdsl/xform.py
third_party/rust/cranelift-codegen/meta-python/gen_encoding.py
third_party/rust/cranelift-codegen/meta-python/gen_instr.py
third_party/rust/cranelift-codegen/meta-python/gen_registers.py
third_party/rust/cranelift-codegen/meta-python/gen_types.py
third_party/rust/cranelift-codegen/meta-python/isa/riscv/recipes.py
third_party/rust/cranelift-codegen/meta-python/isa/x86/encodings.py
third_party/rust/cranelift-codegen/meta-python/isa/x86/recipes.py
third_party/rust/cranelift-codegen/meta-python/isa/x86/registers.py
third_party/rust/cranelift-codegen/meta-python/semantics/__init__.py
third_party/rust/cranelift-codegen/src/binemit/memorysink.rs
third_party/rust/cranelift-codegen/src/binemit/mod.rs
third_party/rust/cranelift-codegen/src/binemit/relaxation.rs
third_party/rust/cranelift-codegen/src/binemit/shrink.rs
third_party/rust/cranelift-codegen/src/cfg_printer.rs
third_party/rust/cranelift-codegen/src/context.rs
third_party/rust/cranelift-codegen/src/cursor.rs
third_party/rust/cranelift-codegen/src/dominator_tree.rs
third_party/rust/cranelift-codegen/src/flowgraph.rs
third_party/rust/cranelift-codegen/src/ir/builder.rs
third_party/rust/cranelift-codegen/src/ir/dfg.rs
third_party/rust/cranelift-codegen/src/ir/extfunc.rs
third_party/rust/cranelift-codegen/src/ir/function.rs
third_party/rust/cranelift-codegen/src/ir/globalvalue.rs
third_party/rust/cranelift-codegen/src/ir/immediates.rs
third_party/rust/cranelift-codegen/src/ir/instructions.rs
third_party/rust/cranelift-codegen/src/ir/jumptable.rs
third_party/rust/cranelift-codegen/src/ir/layout.rs
third_party/rust/cranelift-codegen/src/ir/libcall.rs
third_party/rust/cranelift-codegen/src/ir/memflags.rs
third_party/rust/cranelift-codegen/src/ir/mod.rs
third_party/rust/cranelift-codegen/src/ir/stackslot.rs
third_party/rust/cranelift-codegen/src/ir/types.rs
third_party/rust/cranelift-codegen/src/isa/arm32/mod.rs
third_party/rust/cranelift-codegen/src/isa/arm64/mod.rs
third_party/rust/cranelift-codegen/src/isa/call_conv.rs
third_party/rust/cranelift-codegen/src/isa/enc_tables.rs
third_party/rust/cranelift-codegen/src/isa/encoding.rs
third_party/rust/cranelift-codegen/src/isa/mod.rs
third_party/rust/cranelift-codegen/src/isa/registers.rs
third_party/rust/cranelift-codegen/src/isa/riscv/enc_tables.rs
third_party/rust/cranelift-codegen/src/isa/riscv/mod.rs
third_party/rust/cranelift-codegen/src/isa/x86/abi.rs
third_party/rust/cranelift-codegen/src/isa/x86/binemit.rs
third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs
third_party/rust/cranelift-codegen/src/isa/x86/mod.rs
third_party/rust/cranelift-codegen/src/legalizer/boundary.rs
third_party/rust/cranelift-codegen/src/legalizer/globalvalue.rs
third_party/rust/cranelift-codegen/src/legalizer/mod.rs
third_party/rust/cranelift-codegen/src/lib.rs
third_party/rust/cranelift-codegen/src/loop_analysis.rs
third_party/rust/cranelift-codegen/src/postopt.rs
third_party/rust/cranelift-codegen/src/predicates.rs
third_party/rust/cranelift-codegen/src/preopt.rs
third_party/rust/cranelift-codegen/src/print_errors.rs
third_party/rust/cranelift-codegen/src/regalloc/coloring.rs
third_party/rust/cranelift-codegen/src/regalloc/liveness.rs
third_party/rust/cranelift-codegen/src/regalloc/liverange.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/settings.rs
third_party/rust/cranelift-codegen/src/simple_gvn.rs
third_party/rust/cranelift-codegen/src/simple_preopt.rs
third_party/rust/cranelift-codegen/src/timing.rs
third_party/rust/cranelift-codegen/src/topo_order.rs
third_party/rust/cranelift-codegen/src/verifier/flags.rs
third_party/rust/cranelift-codegen/src/verifier/locations.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/LICENSE
third_party/rust/cranelift-entity/README.md
third_party/rust/cranelift-entity/src/lib.rs
third_party/rust/cranelift-entity/src/list.rs
third_party/rust/cranelift-entity/src/map.rs
third_party/rust/cranelift-entity/src/primary.rs
third_party/rust/cranelift-entity/src/set.rs
third_party/rust/cranelift-entity/src/sparse.rs
third_party/rust/cranelift-frontend/.cargo-checksum.json
third_party/rust/cranelift-frontend/Cargo.toml
third_party/rust/cranelift-frontend/LICENSE
third_party/rust/cranelift-frontend/src/frontend.rs
third_party/rust/cranelift-frontend/src/lib.rs
third_party/rust/cranelift-frontend/src/ssa.rs
third_party/rust/cranelift-frontend/src/switch.rs
third_party/rust/cranelift-wasm/.cargo-checksum.json
third_party/rust/cranelift-wasm/Cargo.toml
third_party/rust/cranelift-wasm/LICENSE
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/mod.rs
third_party/rust/cranelift-wasm/src/environ/spec.rs
third_party/rust/cranelift-wasm/src/func_translator.rs
third_party/rust/cranelift-wasm/src/lib.rs
third_party/rust/cranelift-wasm/src/module_translator.rs
third_party/rust/cranelift-wasm/src/sections_translator.rs
third_party/rust/cranelift-wasm/src/state.rs
third_party/rust/cranelift-wasm/src/translation_utils.rs
third_party/rust/cranelift-wasm/tests/wasm_testsuite.rs
third_party/rust/failure/.cargo-checksum.json
third_party/rust/failure/Cargo.toml
third_party/rust/failure/RELEASES.md
third_party/rust/failure/book/src/SUMMARY.md
third_party/rust/failure/book/src/fail.md
third_party/rust/failure/book/src/string-custom-error.md
third_party/rust/failure/examples/error_as_cause.rs
third_party/rust/failure/examples/string_custom_error_pattern.rs
third_party/rust/failure/src/as_fail.rs
third_party/rust/failure/src/context.rs
third_party/rust/failure/src/error/error_impl.rs
third_party/rust/failure/src/error/mod.rs
third_party/rust/failure/src/lib.rs
third_party/rust/failure/src/macros.rs
third_party/rust/failure_derive/.cargo-checksum.json
third_party/rust/failure_derive/Cargo.toml
third_party/rust/failure_derive/src/lib.rs
third_party/rust/synstructure/.cargo-checksum.json
third_party/rust/synstructure/Cargo.toml
third_party/rust/synstructure/src/lib.rs
third_party/rust/synstructure/src/macros.rs
third_party/rust/target-lexicon/.cargo-checksum.json
third_party/rust/target-lexicon/Cargo.toml
third_party/rust/target-lexicon/LICENSE
third_party/rust/target-lexicon/src/lib.rs
third_party/rust/target-lexicon/src/targets.rs
third_party/rust/target-lexicon/src/triple.rs
third_party/rust/wasmparser/.cargo-checksum.json
third_party/rust/wasmparser/Cargo.toml
third_party/rust/wasmparser/LICENSE
third_party/rust/wasmparser/check-rustfmt.sh
third_party/rust/wasmparser/examples/dump.rs
third_party/rust/wasmparser/examples/simple.rs
third_party/rust/wasmparser/format-all.sh
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/primitives.rs
third_party/rust/wasmparser/src/readers/code_section.rs
third_party/rust/wasmparser/src/readers/data_section.rs
third_party/rust/wasmparser/src/readers/element_section.rs
third_party/rust/wasmparser/src/readers/export_section.rs
third_party/rust/wasmparser/src/readers/function_section.rs
third_party/rust/wasmparser/src/readers/global_section.rs
third_party/rust/wasmparser/src/readers/import_section.rs
third_party/rust/wasmparser/src/readers/init_expr.rs
third_party/rust/wasmparser/src/readers/linking_section.rs
third_party/rust/wasmparser/src/readers/memory_section.rs
third_party/rust/wasmparser/src/readers/mod.rs
third_party/rust/wasmparser/src/readers/module.rs
third_party/rust/wasmparser/src/readers/name_section.rs
third_party/rust/wasmparser/src/readers/operators.rs
third_party/rust/wasmparser/src/readers/reloc_section.rs
third_party/rust/wasmparser/src/readers/section_reader.rs
third_party/rust/wasmparser/src/readers/sourcemappingurl_section.rs
third_party/rust/wasmparser/src/readers/start_section.rs
third_party/rust/wasmparser/src/readers/table_section.rs
third_party/rust/wasmparser/src/readers/type_section.rs
third_party/rust/wasmparser/src/tests.rs
third_party/rust/wasmparser/src/validator.rs
third_party/rust/wasmparser/test-all.sh
third_party/rust/wasmparser/test-no_std.sh
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -156,21 +156,21 @@ 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.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-wasm 0.20.1 (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)",
+ "target-lexicon 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "base64"
 version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -452,71 +452,67 @@ 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.20.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.20.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.23.0"
+version = "0.20.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)",
- "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)",
+ "cranelift-bforest 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-codegen-meta 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-entity 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.2 (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)",
+ "target-lexicon 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.23.0"
+version = "0.20.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)",
-]
 
 [[package]]
 name = "cranelift-entity"
-version = "0.23.0"
+version = "0.20.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.23.0"
+version = "0.20.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)",
- "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)",
+ "cranelift-codegen 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-wasm"
-version = "0.23.0"
+version = "0.20.1"
 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)",
- "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)",
+ "cranelift-codegen 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-entity 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-frontend 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.2 (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)",
+ "target-lexicon 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasmparser 0.17.2 (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)",
@@ -843,32 +839,32 @@ version = "0.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "failure"
-version = "0.1.3"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "failure_derive"
-version = "0.1.3"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "fake-simd"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -2018,17 +2014,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "redox_users"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "regex"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2067,17 +2063,17 @@ dependencies = [
 
 [[package]]
 name = "rkv"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lmdb-rkv 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2489,32 +2485,32 @@ dependencies = [
  "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "synstructure"
-version = "0.10.1"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "target-lexicon"
-version = "0.2.0"
+version = "0.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "tempdir"
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -2894,17 +2890,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.17.2"
 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 +3157,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.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e96851b525021dd220259b9f29bf79d83f65b49e4f12b786d545aa929e4cad2"
+"checksum cranelift-codegen 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16f418f1d1e6221812a7d35cff5b9a572dc978c002e33792134bbd50c07cacca"
+"checksum cranelift-codegen-meta 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1da3daa0109e7a0b7b322cea666cc223fb6a0d5170e83d23b3d5d2deaddca5f3"
+"checksum cranelift-entity 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)" = "27412f153f2b517125dea9247ee8859a9ea3923d44384d54420e64fab9314752"
+"checksum cranelift-frontend 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03c44cc7006b375e60e0c7edb6fc81abfbf20158374c03f5d0da981b373860a3"
+"checksum cranelift-wasm 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a9d3454bf60ee6c3d1f54d6cf9ed82cfc1a2e7efb9ec1b16666bf2987c88bfa"
 "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"
@@ -3200,18 +3196,18 @@ dependencies = [
 "checksum dwrote 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b5a0af6d47ecf67355dc36e5fc09547050bd8a4b87870e637911ffe4aced32a"
 "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
 "checksum ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dc8393b3c7352f94092497f6b52019643e493b6b890eb417cdb7c46117e621"
 "checksum encoding_c 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "769ecb8b33323998e482b218c0d13cd64c267609023b4b7ec3ee740714c318ee"
 "checksum encoding_rs 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a79fa56c329a5b087de13748054fb3b974c4a672c12c71f0b66e35c5addec5"
 "checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
 "checksum euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70a2ebdf55fb9d6329046e026329a55ef8fbaae5ea833f56e170beb3125a8a5f"
-"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
-"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596"
+"checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9"
+"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426"
 "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
 "checksum fixedbitset 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "85cb8fec437468d86dc7c83ca7cfc933341d561873275f22dd5eedefa63a6478"
 "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ebc04f19019fff1f2d627b5581574ead502f80c48c88900575a46e0840fe5d0"
 "checksum freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b659e75b7a7338fe75afd7f909fc2b71937845cffb6ebe54ba2e50f13d8e903d"
 "checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
 "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
@@ -3346,19 +3342,19 @@ dependencies = [
 "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
 "checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7"
 "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
 "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59"
 "checksum syn 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4b5274d4a0a3d2749d5c158dc64d3403e60554dc61194648787ada5212473d"
 "checksum syn 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)" = "455a6ec9b368f8c479b0ae5494d13b22dc00990d2f00d68c9dc6a2dc4f17f210"
-"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
 "checksum synstructure 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "98cad891cd238c98e1f0aec9f7c0f620aa696e4e5f7daba56ac67b5e86a6b049"
-"checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9"
+"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7"
+"checksum target-lexicon 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a34226bd63b5a26fc909f5f0d7ef4dc55d5851077035e49437e4e14bf567247f"
 "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
 "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
 "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
 "checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83"
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
 "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
 "checksum thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
 "checksum thin-vec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73fdf4b84c65a85168477b7fb6c498e0716bc9487fba24623389ea7f51708044"
@@ -3391,17 +3387,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.17.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fed18a63a6796175be2254fccca1da4e8b8fec0abca37ad155aea345feb50798"
 "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,19 +3,19 @@ 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"
-target-lexicon = "0.2.0"
+cranelift-codegen = "0.20.0"
+cranelift-wasm = "0.20.1"
+target-lexicon = "0.0.3"
 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.
 #[profile.release]
--- a/js/src/wasm/cranelift/src/baldrdash.rs
+++ b/js/src/wasm/cranelift/src/baldrdash.rs
@@ -11,16 +11,19 @@
  * 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.
  */
 
 // Safe wrappers to the low-level ABI.  This re-exports all types in
 // baldrapi but none of the functions.
 
+// TODO: Should many u32 arguments and return values here really be
+// usize, to be more conventional?
+
 use baldrapi::CraneliftModuleEnvironment;
 use cranelift_codegen::binemit::CodeOffset;
 use cranelift_codegen::cursor::{Cursor, FuncCursor};
 use cranelift_codegen::entity::EntityRef;
 use cranelift_codegen::ir::immediates::{Ieee32, Ieee64};
 use cranelift_codegen::ir::stackslot::StackSize;
 use cranelift_codegen::ir::{self, InstBuilder};
 use cranelift_codegen::{CodegenError, CodegenResult};
@@ -192,20 +195,20 @@ impl<'a> ModuleEnvironment<'a> {
     }
     pub fn func_import_tls_offset(&self, func_index: FuncIndex) -> usize {
         unsafe { baldrapi::env_func_import_tls_offset(self.env, func_index.index()) }
     }
     pub fn func_is_import(&self, func_index: FuncIndex) -> bool {
         unsafe { baldrapi::env_func_is_import(self.env, func_index.index()) }
     }
     pub fn signature(&self, sig_index: SignatureIndex) -> FuncTypeWithId {
-        FuncTypeWithId(unsafe { baldrapi::env_signature(self.env, sig_index.index()) })
+        FuncTypeWithId(unsafe { baldrapi::env_signature(self.env, sig_index) })
     }
     pub fn table(&self, table_index: TableIndex) -> TableDesc {
-        TableDesc(unsafe { baldrapi::env_table(self.env, table_index.index()) })
+        TableDesc(unsafe { baldrapi::env_table(self.env, table_index) })
     }
     pub fn global(&self, global_index: GlobalIndex) -> GlobalDesc {
-        GlobalDesc(unsafe { baldrapi::env_global(self.env, global_index.index()) })
+        GlobalDesc(unsafe { baldrapi::env_global(self.env, global_index) })
     }
     pub fn min_memory_length(&self) -> i64 {
         self.env.min_memory_length as i64
     }
 }
--- a/js/src/wasm/cranelift/src/compile.rs
+++ b/js/src/wasm/cranelift/src/compile.rs
@@ -87,18 +87,19 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
             isa: make_isa(static_environ)?,
             context: cranelift_codegen::Context::new(),
             trans: cranelift_wasm::FuncTranslator::new(),
             current_func: CompiledFunc::new(),
         })
     }
 
     pub fn compile(&mut self) -> CodegenResult<()> {
-        let size = self.context.compile(&*self.isa)?;
-        self.binemit(size as usize)
+        let orig_size = self.context.compile(&*self.isa)?;
+        let size = self.remove_return_inst(orig_size) as usize;
+        self.binemit(size)
     }
 
     /// Translate the WebAssembly code to Cranelift IR.
     pub fn translate_wasm(
         &mut self,
         func: &bd::FuncCompileInput,
     ) -> WasmResult<bd::FuncTypeWithId> {
         self.context.clear();
@@ -113,16 +114,47 @@ impl<'a, 'b> BatchCompiler<'a, 'b> {
         self.trans
             .translate(func.bytecode(), &mut self.context.func, tenv)?;
 
         info!("Translated wasm function {}.", func.index);
         debug!("Content: {}", self.context.func.display(&*self.isa));
         Ok(wsig)
     }
 
+    /// Remove the trailing return instruction from the current function to make room for a custom
+    /// epilogue.
+    ///
+    /// Return the new function size in bytes, adjusted from size.
+    fn remove_return_inst(&mut self, size: CodeOffset) -> CodeOffset {
+        // Get the last instruction in the function.
+        let mut pos = FuncCursor::new(&mut self.context.func);
+
+        // Move to the bottom of the last EBB in the function.
+        pos.prev_ebb().expect("empty function");
+
+        // Move to the last instruction in the last EBB.
+        let inst = pos.prev_inst().expect("last EBB has not terminator");
+
+        // TODO There might be an issue here, if there can be more than one
+        // IR returns per IR function.
+
+        if pos.func.dfg[inst].opcode().is_return() {
+            let enc = pos.func.encodings[inst];
+            let ret_size = self.isa.encoding_info().bytes(enc);
+            // Remove the return instruction. This leaves the IR in an invalid state where the last
+            // EBB has no terminator. The code emitter shouldn't mind this. If it does want to
+            // verify the IR in the future, we could use a zero-sized return encoding instead.
+            pos.remove_inst();
+            return size - ret_size;
+        }
+
+        // Function doesn't have a return instruction.
+        size
+    }
+
     /// Emit binary machine code to `emitter`.
     fn binemit(&mut self, size: usize) -> CodegenResult<()> {
         let frame_pushed = self.frame_pushed();
         let contains_calls = self.contains_calls();
 
         info!("Emitting {} bytes, frame_pushed={}\n.", size, frame_pushed);
 
         self.current_func.reset(frame_pushed, contains_calls);
--- a/js/src/wasm/cranelift/src/cpu.rs
+++ b/js/src/wasm/cranelift/src/cpu.rs
@@ -28,23 +28,32 @@ use std::mem;
 use std::str::FromStr;
 use target_lexicon;
 use utils::{BasicError, DashResult};
 
 use baldrdash::StaticEnvironment;
 
 impl From<isa::LookupError> for BasicError {
     fn from(err: isa::LookupError) -> BasicError {
-        BasicError::new(err.to_string())
+        let msg = match err {
+            isa::LookupError::SupportDisabled => "ISA support is disabled",
+            isa::LookupError::Unsupported => "unsupported ISA",
+        };
+        BasicError::new(msg.to_string())
     }
 }
 
 impl From<settings::SetError> for BasicError {
     fn from(err: settings::SetError) -> BasicError {
-        BasicError::new(err.to_string())
+        let msg = match err {
+            settings::SetError::BadName => "bad setting name",
+            settings::SetError::BadType => "bad setting type",
+            settings::SetError::BadValue => "bad setting value",
+        };
+        BasicError::new(msg.to_string())
     }
 }
 
 /// Allocate a `TargetISA` object that can be used to generate code for the CPU we're running on.
 ///
 /// TODO: SM runs on more than x86 chips. Support them.
 ///
 /// # Errors
@@ -89,16 +98,20 @@ pub fn make_isa(env: &StaticEnvironment)
 }
 
 /// Create a `Flags` object for the shared settings.
 ///
 /// This only fails if one of Cranelift's settings has been removed or renamed.
 fn make_shared_flags() -> settings::SetResult<settings::Flags> {
     let mut sb = settings::builder();
 
+    // Since we're using SM's epilogue insertion code, we can only handle a single return
+    // instruction at the end of the function.
+    sb.enable("return_at_end")?;
+
     // We don't install SIGFPE handlers, but depend on explicit traps around divisions.
     sb.enable("avoid_div_traps")?;
 
     // Cranelift needs to know how many words are pushed by `GenerateFunctionPrologue` so it can
     // compute frame pointer offsets accurately.
     //
     // 1. Return address (whether explicitly pushed on ARM or implicitly on x86).
     // 2. TLS register.
@@ -117,13 +130,10 @@ fn make_shared_flags() -> settings::SetR
     }
 
     // Baldrdash does its own stack overflow checks, so we don't need Cranelift doing any for us.
     sb.set("probestack_enabled", "false")?;
 
     // Let's optimize for speed.
     sb.set("opt_level", "best")?;
 
-    // TODO: Enable jump tables (requires emitting readonly data separately from text).
-    sb.set("jump_tables_enabled", "false")?;
-
     Ok(settings::Flags::new(sb))
 }
--- a/js/src/wasm/cranelift/src/wasm2clif.rs
+++ b/js/src/wasm/cranelift/src/wasm2clif.rs
@@ -16,25 +16,25 @@
 //! This module deals with the translation of WebAssembly binary functions to Cranelift IR.
 //!
 //! The code here deals with adapting the `cranelift_wasm` module to the specifics of BaldrMonkey's
 //! internal data structures.
 
 use baldrdash as bd;
 use compile::{symbolic_function_name, wasm_function_name};
 use cranelift_codegen::cursor::{Cursor, FuncCursor};
-use cranelift_codegen::entity::{EntityRef, PrimaryMap, SecondaryMap};
+use cranelift_codegen::entity::EntityMap;
 use cranelift_codegen::ir;
 use cranelift_codegen::ir::condcodes::IntCC;
 use cranelift_codegen::ir::InstBuilder;
-use cranelift_codegen::isa::{CallConv, TargetFrontendConfig, TargetIsa};
+use cranelift_codegen::isa::TargetIsa;
 use cranelift_codegen::packed_option::PackedOption;
-use cranelift_codegen::settings::Flags;
+use cranelift_codegen::settings::{CallConv, Flags};
 use cranelift_wasm::{
-    self, FuncIndex, GlobalIndex, MemoryIndex, ReturnMode, SignatureIndex, TableIndex, WasmResult,
+    self, FuncIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex, WasmResult,
 };
 use std::collections::HashMap;
 use target_lexicon::Triple;
 
 /// Get the integer type used for representing pointers on this platform.
 fn native_pointer_type() -> ir::Type {
     if cfg!(target_pointer_width = "64") {
         ir::types::I64
@@ -53,21 +53,16 @@ pub fn native_pointer_size() -> i32 {
 }
 
 /// Convert a TlsData offset into a `Offset32` for a global decl.
 fn offset32(offset: usize) -> ir::immediates::Offset32 {
     assert!(offset <= i32::max_value() as usize);
     (offset as i32).into()
 }
 
-/// Convert a usize offset into a `Imm64` for an iadd_imm.
-fn imm64(offset: usize) -> ir::immediates::Imm64 {
-    (offset as i64).into()
-}
-
 /// Initialize a `Signature` from a wasm signature.
 fn init_sig_from_wsig(sig: &mut ir::Signature, wsig: bd::FuncTypeWithId) {
     sig.clear(CallConv::Baldrdash);
     for &arg in wsig.args() {
         sig.params.push(ir::AbiParam::new(arg.into()));
     }
 
     if let Some(ret_type) = wsig.ret_type().into() {
@@ -102,36 +97,33 @@ pub fn init_sig(
 /// A `TargetIsa` and `ModuleEnvironment` joined so we can implement `FuncEnvironment`.
 pub struct TransEnv<'a, 'b, 'c> {
     isa: &'a TargetIsa,
     env: &'b bd::ModuleEnvironment<'b>,
     static_env: &'c bd::StaticEnvironment,
 
     /// Information about the function pointer tables `self.env` knowns about. Indexed by table
     /// index.
-    tables: PrimaryMap<TableIndex, TableInfo>,
+    tables: Vec<TableInfo>,
 
     /// For those signatures whose ID is stored in a global, keep track of the globals we have
     /// created so far.
     ///
     /// Note that most signatures are of the immediate form, and we don't keep any records for
     /// those.
     ///
     /// The key to this table is the TLS offset returned by `sig_idTlsOffset()`.
     signatures: HashMap<i32, ir::GlobalValue>,
 
     /// Global variables containing `FuncImportTls` information about imported functions.
     /// This vector is indexed by a `FuncIndex`, taking advantage of the fact that WebAssembly
     /// imported functions are numbered starting from 0.
     ///
     /// Any `None` entries in this table are simply global variables that have not yet been created.
-    func_gvs: SecondaryMap<FuncIndex, PackedOption<ir::GlobalValue>>,
-
-    /// The `vmctx` global value.
-    vmctx_gv: PackedOption<ir::GlobalValue>,
+    func_gvs: EntityMap<FuncIndex, PackedOption<ir::GlobalValue>>,
 
     /// Global variable representing the `TlsData::instance` field which points to the current
     /// instance.
     instance_gv: PackedOption<ir::GlobalValue>,
 
     /// Global variable representing the `TlsData::interrupt` field which points to the current
     /// interrupt flag.
     interrupt_gv: PackedOption<ir::GlobalValue>,
@@ -152,116 +144,93 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
         isa: &'a TargetIsa,
         env: &'b bd::ModuleEnvironment,
         static_env: &'c bd::StaticEnvironment,
     ) -> Self {
         TransEnv {
             isa,
             env,
             static_env,
-            tables: PrimaryMap::new(),
+            tables: Vec::new(),
             signatures: HashMap::new(),
-            func_gvs: SecondaryMap::new(),
-            vmctx_gv: None.into(),
+            func_gvs: EntityMap::new(),
             instance_gv: None.into(),
             interrupt_gv: None.into(),
             symbolic: [None.into(); 2],
             cx_addr: None.into(),
             realm_addr: None.into(),
         }
     }
 
-    /// Get the `vmctx` global value.
-    fn get_vmctx_gv(&mut self, func: &mut ir::Function) -> ir::GlobalValue {
-        match self.vmctx_gv.expand() {
-            Some(gv) => gv,
-            None => {
-                // We need to allocate the global variable.
-                let gv = func.create_global_value(ir::GlobalValueData::VMContext);
-                self.vmctx_gv = Some(gv).into();
-                gv
-            }
-        }
-    }
-
     /// Get information about `table`.
     /// Create it if necessary.
     fn get_table(&mut self, func: &mut ir::Function, table: TableIndex) -> TableInfo {
         // Allocate all tables up to the requested index.
-        let vmctx = self.get_vmctx_gv(func);
-        while self.tables.len() <= table.index() {
-            let wtab = self.env.table(TableIndex::new(self.tables.len()));
-            self.tables.push(TableInfo::new(wtab, func, vmctx));
+        while self.tables.len() <= table {
+            let wtab = self.env.table(self.tables.len());
+            self.tables.push(TableInfo::new(wtab, func));
         }
         self.tables[table].clone()
     }
 
     /// Get the global variable storing the ID of the given signature.
     fn sig_global(&mut self, func: &mut ir::Function, offset: usize) -> ir::GlobalValue {
-        let vmctx = self.get_vmctx_gv(func);
         *self.signatures.entry(offset as i32).or_insert_with(|| {
-            func.create_global_value(ir::GlobalValueData::IAddImm {
-                base: vmctx,
-                offset: imm64(offset),
-                global_type: native_pointer_type(),
+            func.create_global_value(ir::GlobalValueData::VMContext {
+                offset: offset32(offset),
             })
         })
     }
 
     /// Get the global variable storing the `FuncImportTls` struct for an imported function.
     fn func_import_global(&mut self, func: &mut ir::Function, index: FuncIndex) -> ir::GlobalValue {
         // See if we already allocated a global for this import.
         if let Some(gv) = self.func_gvs.get(index).and_then(|gv| gv.expand()) {
             return gv;
         }
         // We need to create a global variable for `import_index`.
-        let vmctx = self.get_vmctx_gv(func);
-        let gv = func.create_global_value(ir::GlobalValueData::IAddImm {
-            base: vmctx,
-            offset: imm64(self.env.func_import_tls_offset(index)),
-            global_type: native_pointer_type(),
+        let gv = func.create_global_value(ir::GlobalValueData::VMContext {
+            offset: offset32(self.env.func_import_tls_offset(index)),
         });
         // Save it for next time.
         self.func_gvs[index] = gv.into();
         gv
     }
 
     /// Generate code that loads the current instance pointer.
     fn load_instance(&mut self, pos: &mut FuncCursor) -> ir::Value {
         let gv = match self.instance_gv.expand() {
             Some(gv) => gv,
             None => {
                 // We need to allocate the global variable.
-                let vmctx = self.get_vmctx_gv(pos.func);
-                let gv = pos.func.create_global_value(ir::GlobalValueData::IAddImm {
-                    base: vmctx,
-                    offset: imm64(self.static_env.instanceTlsOffset),
-                    global_type: native_pointer_type(),
-                });
+                let gv = pos
+                    .func
+                    .create_global_value(ir::GlobalValueData::VMContext {
+                        offset: offset32(self.static_env.instanceTlsOffset),
+                    });
                 self.instance_gv = gv.into();
                 gv
             }
         };
         let ga = pos.ins().global_value(native_pointer_type(), gv);
         pos.ins()
             .load(native_pointer_type(), ir::MemFlags::new(), ga, 0)
     }
 
     /// Generate code that loads the current instance pointer.
     fn load_interrupt_flag(&mut self, pos: &mut FuncCursor) -> ir::Value {
         let gv = match self.interrupt_gv.expand() {
             Some(gv) => gv,
             None => {
                 // We need to allocate the global variable.
-                let vmctx = self.get_vmctx_gv(pos.func);
-                let gv = pos.func.create_global_value(ir::GlobalValueData::IAddImm {
-                    base: vmctx,
-                    offset: imm64(self.static_env.interruptTlsOffset),
-                    global_type: native_pointer_type(),
-                });
+                let gv = pos
+                    .func
+                    .create_global_value(ir::GlobalValueData::VMContext {
+                        offset: offset32(self.static_env.interruptTlsOffset),
+                    });
                 self.interrupt_gv = gv.into();
                 gv
             }
         };
         let ga = pos.ins().global_value(native_pointer_type(), gv);
         pos.ins()
             .load(native_pointer_type(), ir::MemFlags::new(), ga, 0)
     }
@@ -290,33 +259,27 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
         self.symbolic[symidx] = fnref.into();
         (fnref, signature)
     }
 
     /// Update the JSContext's realm value. This is called after a call to restore the
     /// realm value, in case the call has used a different realm.
     fn switch_to_wasm_tls_realm(&mut self, pos: &mut FuncCursor) {
         if self.cx_addr.is_none() {
-            let vmctx = self.get_vmctx_gv(&mut pos.func);
             self.cx_addr = pos
                 .func
-                .create_global_value(ir::GlobalValueData::IAddImm {
-                    base: vmctx,
-                    offset: imm64(self.static_env.cxTlsOffset),
-                    global_type: native_pointer_type(),
+                .create_global_value(ir::GlobalValueData::VMContext {
+                    offset: offset32(self.static_env.cxTlsOffset),
                 }).into();
         }
         if self.realm_addr.is_none() {
-            let vmctx = self.get_vmctx_gv(&mut pos.func);
             self.realm_addr = pos
                 .func
-                .create_global_value(ir::GlobalValueData::IAddImm {
-                    base: vmctx,
-                    offset: imm64(self.static_env.realmTlsOffset),
-                    global_type: native_pointer_type(),
+                .create_global_value(ir::GlobalValueData::VMContext {
+                    offset: offset32(self.static_env.realmTlsOffset),
                 }).into();
         }
 
         let ptr = native_pointer_type();
         let mut flags = ir::MemFlags::new();
         flags.set_aligned();
         flags.set_notrap();
 
@@ -369,18 +332,22 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
             offset32(self.static_env.realmFuncImportTlsOffset),
         );
         pos.ins()
             .store(flags, realm, cx, offset32(self.static_env.realmCxOffset));
     }
 }
 
 impl<'a, 'b, 'c> cranelift_wasm::FuncEnvironment for TransEnv<'a, 'b, 'c> {
-    fn target_config(&self) -> TargetFrontendConfig {
-        self.isa.frontend_config()
+    fn flags(&self) -> &Flags {
+        self.isa.flags()
+    }
+
+    fn triple(&self) -> &Triple {
+        self.isa.triple()
     }
 
     fn pointer_type(&self) -> ir::Type {
         native_pointer_type()
     }
 
     fn make_global(
         &mut self,
@@ -392,72 +359,66 @@ impl<'a, 'b, 'c> cranelift_wasm::FuncEnv
             // Constant globals have a known value at compile time. We insert an instruction to
             // materialize the constant at the front of the entry block.
             let mut pos = FuncCursor::new(func);
             pos.next_ebb().expect("empty function");
             pos.next_inst();
             cranelift_wasm::GlobalVariable::Const(global.emit_constant(&mut pos))
         } else {
             // This is a global variable. Here we don't care if it is mutable or not.
-            let offset = global.tls_offset();
-            let mut gv = self.get_vmctx_gv(func);
+            let offset = offset32(global.tls_offset());
+            let mut gv = func.create_global_value(ir::GlobalValueData::VMContext { offset });
 
             // Some globals are represented as a pointer to the actual data, in which case we
             // must do an extra dereference to get to them.
             if global.is_indirect() {
-                gv = func.create_global_value(ir::GlobalValueData::Load {
+                gv = func.create_global_value(ir::GlobalValueData::Deref {
                     base: gv,
-                    offset: offset32(offset),
-                    global_type: native_pointer_type(),
-                    readonly: false,
-                });
-            } else {
-                gv = func.create_global_value(ir::GlobalValueData::IAddImm {
-                    base: gv,
-                    offset: imm64(offset),
-                    global_type: native_pointer_type(),
+                    offset: offset32(0),
+                    memory_type: native_pointer_type(),
                 });
             }
 
             // Create a Cranelift global variable. We don't need to remember the reference, the
             // function translator does that for us.
             cranelift_wasm::GlobalVariable::Memory {
                 gv,
                 ty: global.value_type().into(),
             }
         }
     }
 
     fn make_heap(&mut self, func: &mut ir::Function, index: MemoryIndex) -> ir::Heap {
-        assert_eq!(index.index(), 0, "Only one WebAssembly memory supported");
+        assert_eq!(index, 0, "Only one WebAssembly memory supported");
         // Get the address of the `TlsData::memoryBase` field.
-        let base_addr = self.get_vmctx_gv(func);
-        // Get the `TlsData::memoryBase` field. We assume this is never modified during execution
-        // of the function.
-        let base = func.create_global_value(ir::GlobalValueData::Load {
+        let base_addr =
+            func.create_global_value(ir::GlobalValueData::VMContext { offset: 0.into() });
+        // Get the `TlsData::memoryBase` field.
+        let base = func.create_global_value(ir::GlobalValueData::Deref {
             base: base_addr,
             offset: offset32(0),
-            global_type: native_pointer_type(),
-            readonly: true,
+            memory_type: native_pointer_type(),
         });
         let min_size = ir::immediates::Imm64::new(self.env.min_memory_length());
-        let guard_size = imm64(self.static_env.memoryGuardSize);
+        let guard_size = ir::immediates::Imm64::new(self.static_env.memoryGuardSize as i64);
 
         let bound = self.static_env.staticMemoryBound;
         let style = if bound > 0 {
             // We have a static heap.
             let bound = (bound as i64).into();
             ir::HeapStyle::Static { bound }
         } else {
+            let offset = native_pointer_size().into();
+            // Get the address of the `TlsData::boundsCheckLimit` field.
+            let bound_gv_addr = func.create_global_value(ir::GlobalValueData::VMContext { offset });
             // Get the `TlsData::boundsCheckLimit` field.
-            let bound_gv = func.create_global_value(ir::GlobalValueData::Load {
-                base: base_addr,
-                offset: native_pointer_size().into(),
-                global_type: ir::types::I32,
-                readonly: false,
+            let bound_gv = func.create_global_value(ir::GlobalValueData::Deref {
+                base: bound_gv_addr,
+                offset: offset32(0),
+                memory_type: ir::types::I32,
             });
             ir::HeapStyle::Dynamic { bound_gv }
         };
 
         func.create_heap(ir::HeapData {
             base,
             min_size,
             guard_size,
@@ -482,28 +443,26 @@ impl<'a, 'b, 'c> cranelift_wasm::FuncEnv
         func.import_signature(sigdata)
     }
 
     fn make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> ir::Table {
         let table_desc = self.get_table(func, index);
 
         // TODO we'd need a better way to synchronize the shape of GlobalDataDesc and these
         // offsets.
-        let bound_gv = func.create_global_value(ir::GlobalValueData::Load {
+        let bound_gv = func.create_global_value(ir::GlobalValueData::Deref {
             base: table_desc.global,
             offset: 0.into(),
-            global_type: ir::types::I32,
-            readonly: false,
+            memory_type: ir::types::I32,
         });
 
-        let base_gv = func.create_global_value(ir::GlobalValueData::Load {
+        let base_gv = func.create_global_value(ir::GlobalValueData::Deref {
             base: table_desc.global,
-            offset: offset32(native_pointer_size() as usize),
-            global_type: native_pointer_type(),
-            readonly: false,
+            offset: native_pointer_size().into(),
+            memory_type: native_pointer_type(),
         });
 
         func.create_table(ir::TableData {
             base_gv,
             min_size: ir::immediates::Imm64::new(0),
             bound_gv,
             element_size: ir::immediates::Imm64::new(i64::from(self.pointer_bytes()) * 2),
             index_type: ir::types::I32,
@@ -532,17 +491,17 @@ impl<'a, 'b, 'c> cranelift_wasm::FuncEnv
         sig_ref: ir::SigRef,
         callee: ir::Value,
         call_args: &[ir::Value],
     ) -> WasmResult<ir::Inst> {
         let wsig = self.env.signature(sig_index);
 
         // TODO: When compiling asm.js, the table index in inferred from the signature index.
         // Currently, WebAssembly doesn't support multiple tables. That may change.
-        assert_eq!(table_index.index(), 0);
+        assert_eq!(table_index, 0);
         let wtable = self.get_table(pos.func, table_index);
 
         // Follows `MacroAssembler::wasmCallIndirect`:
 
         // 1. Materialize the signature ID.
         let sigid_value = match wsig.id_kind() {
             bd::FuncTypeIdDescKind::None => None,
             bd::FuncTypeIdDescKind::Immediate => {
@@ -556,30 +515,34 @@ impl<'a, 'b, 'c> cranelift_wasm::FuncEnv
                 Some(
                     pos.ins()
                         .load(native_pointer_type(), ir::MemFlags::new(), addr, 0),
                 )
             }
         };
 
         // 2. Bounds check the callee against the table length.
-        let (bound_gv, base_gv) = {
-            let table_data = &pos.func.tables[table];
-            (table_data.bound_gv, table_data.base_gv)
-        };
+        // TODO reuse this once !491 is merged.
+        //let (bound_gv, base_gv) = {
+        //let table_data = &pos.func.tables[table];
+        //(table_data.bound_gv, table_data.base_gv)
+        //};
 
-        let tlength = pos.ins().global_value(ir::types::I32, bound_gv);
+        //let tlength = pos.ins().global_value(ir::types::I32, bound_gv);
+        let gv_addr = pos.ins().global_value(native_pointer_type(), wtable.global);
+        let tlength = wtable.load_length(&mut pos, gv_addr);
 
         let oob = pos
             .ins()
             .icmp(IntCC::UnsignedGreaterThanOrEqual, callee, tlength);
         pos.ins().trapnz(oob, ir::TrapCode::OutOfBounds);
 
         // 3. Load the wtable base pointer from a global.
-        let tbase = pos.ins().global_value(native_pointer_type(), base_gv);
+        //let tbase = pos.ins().global_value(native_pointer_type(), base_gv);
+        let tbase = wtable.load_base(&mut pos, gv_addr);
 
         // 4. Load callee pointer from wtable.
         let callee_x = if native_pointer_type() != ir::types::I32 {
             pos.ins().uextend(native_pointer_type(), callee)
         } else {
             callee
         };
         let callee_scaled = pos.ins().imul_imm(callee_x, wtable.entry_size());
@@ -618,17 +581,17 @@ impl<'a, 'b, 'c> cranelift_wasm::FuncEnv
         args.extend(call_args.iter().cloned(), &mut pos.func.dfg.value_lists);
         args.push(vmctx, &mut pos.func.dfg.value_lists);
         if let Some(sigid) = sigid_value {
             args.push(sigid, &mut pos.func.dfg.value_lists);
         }
 
         let call = pos
             .ins()
-            .CallIndirect(ir::Opcode::CallIndirect, ir::types::INVALID, sig_ref, args)
+            .CallIndirect(ir::Opcode::CallIndirect, ir::types::VOID, sig_ref, args)
             .0;
         self.switch_to_wasm_tls_realm(&mut pos);
         Ok(call)
     }
 
     fn translate_call(
         &mut self,
         mut pos: FuncCursor,
@@ -668,33 +631,33 @@ impl<'a, 'b, 'c> cranelift_wasm::FuncEnv
             // Now make an indirect call to `fit_code`.
             // TODO: We don't need the `FuncRef` that was allocated for this callee since we're
             // using an indirect call. We would need to change the `FuncTranslator` interface to
             // deal.
             args.insert(0, fit_code, &mut pos.func.dfg.value_lists);
             let sig = pos.func.dfg.ext_funcs[callee].signature;
             let call = pos
                 .ins()
-                .CallIndirect(ir::Opcode::CallIndirect, ir::types::INVALID, sig, args)
+                .CallIndirect(ir::Opcode::CallIndirect, ir::types::VOID, sig, args)
                 .0;
             self.switch_to_wasm_tls_realm(&mut pos);
             Ok(call)
         } else {
             // This is a call to a local function.
 
             // Then we need to pass on the VM context pointer.
             let vmctx = pos
                 .func
                 .special_param(ir::ArgumentPurpose::VMContext)
                 .expect("Missing vmctx arg");
             args.push(vmctx, &mut pos.func.dfg.value_lists);
 
             Ok(pos
                 .ins()
-                .Call(ir::Opcode::Call, ir::types::INVALID, callee, args)
+                .Call(ir::Opcode::Call, ir::types::VOID, callee, args)
                 .0)
         }
     }
 
     fn translate_memory_grow(
         &mut self,
         mut pos: FuncCursor,
         index: MemoryIndex,
@@ -764,22 +727,16 @@ impl<'a, 'b, 'c> cranelift_wasm::FuncEnv
         self.switch_to_wasm_tls_realm(&mut pos);
         Ok(pos.func.dfg.first_result(call))
     }
 
     fn translate_loop_header(&mut self, mut pos: FuncCursor) {
         let interrupt = self.load_interrupt_flag(&mut pos);
         pos.ins().trapnz(interrupt, ir::TrapCode::Interrupt);
     }
-
-    fn return_mode(&self) -> ReturnMode {
-        // Since we're using SM's epilogue insertion code, we can only handle a single return
-        // instruction at the end of the function.
-        ReturnMode::FallthroughReturn
-    }
 }
 
 /// Information about a function table.
 #[derive(Clone)]
 struct TableInfo {
     /// Global variable containing a `wasm::TableTls` struct with two fields:
     ///
     /// 0: Unsigned 32-bit table length.
@@ -787,26 +744,22 @@ struct TableInfo {
     pub global: ir::GlobalValue,
 
     /// Is this an external table?
     pub external: bool,
 }
 
 impl TableInfo {
     /// Create a TableInfo and its global variable in `func`.
-    pub fn new(wtab: bd::TableDesc, func: &mut ir::Function, vmctx: ir::GlobalValue) -> TableInfo {
+    pub fn new(wtab: bd::TableDesc, func: &mut ir::Function) -> TableInfo {
         // Create the global variable.
         let offset = wtab.tls_offset();
         assert!(offset < i32::max_value() as usize);
-        let offset = imm64(offset);
-        let global = func.create_global_value(ir::GlobalValueData::IAddImm {
-            base: vmctx,
-            offset,
-            global_type: native_pointer_type(),
-        });
+        let offset = (offset as i32).into();
+        let global = func.create_global_value(ir::GlobalValueData::VMContext { offset });
 
         TableInfo {
             global,
             external: wtab.is_external(),
         }
     }
 
     /// Load the table length.
--- 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":"2ac8519f0423d9cc23bc68fb13e4af52ba478dd31c49fdb4cd0a1bd3251d4a48","LICENSE":"a6c48161a09acc75a0e25503bab66a731eb5fba5392ed4bb4743e4ba5085327a","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"569333274dd318ddfe098a9962f353ca45d2702f9a44dfe8180f91c97fa19211","src/map.rs":"1d7882872863386c2576bfcb7c4caf2d135c250feadf82d342ad3682c64d9c7c","src/node.rs":"3943b6126f1b8f83421a9db073db880e80003d93458170a36195f06bad452be4","src/path.rs":"28e29259ff6a2ca35adc5a036bebede3f0da39d40c91de27d219ef04dd60f994","src/pool.rs":"d572863b0e2055b13ea4f34a06512778915a98bfe6f9073d3829d26108c506b0","src/set.rs":"879a7469b7f86fe90786945b19d3f85909a651fb9b297d660b4ce118d6718ec6"},"package":"1e96851b525021dd220259b9f29bf79d83f65b49e4f12b786d545aa929e4cad2"}
\ 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.20.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.20.0"
 default-features = false
 
 [features]
 default = ["std"]
 std = ["cranelift-entity/std"]
 [badges.maintenance]
 status = "experimental"
 
--- a/third_party/rust/cranelift-bforest/LICENSE
+++ b/third_party/rust/cranelift-bforest/LICENSE
@@ -212,9 +212,8 @@ with the conditions of Sections 4(a), 4(
 In addition, if you combine or link compiled forms of this Software with
 software that is licensed under the GPLv2 ("Combined Software") and if a
 court of competent jurisdiction determines that the patent provision (Section
 3), the indemnity provision (Section 9) or other Section of the License
 conflicts with the conditions of the GPLv2, you may retroactively and
 prospectively choose to deem waived or otherwise exclude such Section(s) of
 the License, but only in their entirety and only with respect to the Combined
 Software.
-
--- a/third_party/rust/cranelift-bforest/src/lib.rs
+++ b/third_party/rust/cranelift-bforest/src/lib.rs
@@ -11,35 +11,23 @@
 //! - Keys and values are expected to be small and copyable. We optimize for 32-bit types.
 //! - A comparator object is used to compare keys, allowing smaller "context free" keys.
 //! - Empty trees have a very small 32-bit footprint.
 //! - All the trees in a forest can be cleared in constant time.
 
 #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
 #![warn(unused_import_braces)]
 #![cfg_attr(feature = "std", warn(unstable_features))]
-#![cfg_attr(
-    feature = "clippy",
-    plugin(clippy(conf_file = "../../clippy.toml"))
-)]
-#![cfg_attr(
-    feature = "cargo-clippy",
-    allow(new_without_default, new_without_default_derive)
-)]
+#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
+#![cfg_attr(feature = "cargo-clippy", allow(new_without_default, new_without_default_derive))]
 #![cfg_attr(
     feature = "cargo-clippy",
     warn(
-        float_arithmetic,
-        mut_mut,
-        nonminimal_bool,
-        option_map_unwrap_or,
-        option_map_unwrap_or_else,
-        print_stdout,
-        unicode_not_nfc,
-        use_self
+        float_arithmetic, mut_mut, nonminimal_bool, option_map_unwrap_or, option_map_unwrap_or_else,
+        print_stdout, unicode_not_nfc, use_self
     )
 )]
 // Turns on no_std and alloc features if std is not available.
 #![cfg_attr(not(feature = "std"), no_std)]
 #![cfg_attr(not(feature = "std"), feature(alloc))]
 
 /// This replaces `std` in builds with `core`.
 #[cfg(not(feature = "std"))]
@@ -153,17 +141,17 @@ fn slice_insert<T: Copy>(s: &mut [T], i:
 /// Shift elements in `s` to the left by `n` positions.
 fn slice_shift<T: Copy>(s: &mut [T], n: usize) {
     for j in 0..s.len() - n {
         s[j] = s[j + n];
     }
 }
 
 #[cfg(test)]
-mod tests {
+mod test {
     use super::*;
     use entity::EntityRef;
 
     /// An opaque reference to an extended basic block in a function.
     #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
     pub struct Ebb(u32);
     entity_impl!(Ebb, "ebb");
 
--- a/third_party/rust/cranelift-bforest/src/map.rs
+++ b/third_party/rust/cranelift-bforest/src/map.rs
@@ -261,35 +261,38 @@ where
 
 impl<'a, K, V, C> MapCursor<'a, K, V, C>
 where
     K: Copy,
     V: Copy,
     C: Comparator<K>,
 {
     /// Create a cursor with a default (off-the-end) location.
-    fn new(container: &'a mut Map<K, V>, forest: &'a mut MapForest<K, V>, comp: &'a C) -> Self {
-        Self {
+    fn new(
+        container: &'a mut Map<K, V>,
+        forest: &'a mut MapForest<K, V>,
+        comp: &'a C,
+    ) -> MapCursor<'a, K, V, C> {
+        MapCursor {
             root: &mut container.root,
             pool: &mut forest.nodes,
             comp,
             path: Path::default(),
         }
     }
 
     /// Is this cursor pointing to an empty map?
     pub fn is_empty(&self) -> bool {
         self.root.is_none()
     }
 
     /// Move cursor to the next key-value pair and return it.
     ///
     /// If the cursor reaches the end, return `None` and leave the cursor at the off-the-end
     /// position.
-    #[cfg_attr(feature = "cargo-clippy", allow(should_implement_trait))]
     pub fn next(&mut self) -> Option<(K, V)> {
         self.path.next(self.pool)
     }
 
     /// Move cursor to the previous key-value pair and return it.
     ///
     /// If the cursor is already pointing at the first entry, leave it there and return `None`.
     pub fn prev(&mut self) -> Option<(K, V)> {
@@ -421,17 +424,17 @@ where
     /// Get a text version of the path to the current position.
     fn tpath(&self) -> String {
         use std::string::ToString;
         self.path.to_string()
     }
 }
 
 #[cfg(test)]
-mod tests {
+mod test {
     use super::super::NodeData;
     use super::*;
     use std::mem;
     use std::vec::Vec;
 
     #[test]
     fn node_size() {
         // check that nodes are cache line sized when keys and values are 32 bits.
--- a/third_party/rust/cranelift-bforest/src/node.rs
+++ b/third_party/rust/cranelift-bforest/src/node.rs
@@ -100,17 +100,17 @@ impl<F: Forest> NodeData<F> {
             NodeData::Inner {
                 size,
                 ref keys,
                 ref tree,
             } => {
                 let size = usize::from(size);
                 // TODO: We could probably use `get_unchecked()` here since `size` is always in
                 // range.
-                (&keys[0..size], &tree[0..=size])
+                (&keys[0..size], &tree[0..size + 1])
             }
             _ => panic!("Expected inner node"),
         }
     }
 
     /// Unwrap a leaf node into two slices (keys, values) of the same length.
     pub fn unwrap_leaf(&self) -> (&[F::Key], &[F::Value]) {
         match *self {
@@ -170,20 +170,20 @@ impl<F: Forest> NodeData<F> {
                 ref mut size,
                 ref mut keys,
                 ref mut tree,
             } => {
                 let sz = usize::from(*size);
                 debug_assert!(sz <= keys.len());
                 debug_assert!(index <= sz, "Can't insert at {} with {} keys", index, sz);
 
-                if let Some(ks) = keys.get_mut(0..=sz) {
+                if let Some(ks) = keys.get_mut(0..sz + 1) {
                     *size = (sz + 1) as u8;
                     slice_insert(ks, index, key);
-                    slice_insert(&mut tree[1..=sz + 1], index, node);
+                    slice_insert(&mut tree[1..sz + 2], index, node);
                     true
                 } else {
                     false
                 }
             }
             _ => panic!("Expected inner node"),
         }
     }
@@ -198,20 +198,20 @@ impl<F: Forest> NodeData<F> {
                 ref mut vals,
             } => {
                 let sz = usize::from(*size);
                 let keys = keys.borrow_mut();
                 let vals = vals.borrow_mut();
                 debug_assert!(sz <= keys.len());
                 debug_assert!(index <= sz);
 
-                if let Some(ks) = keys.get_mut(0..=sz) {
+                if let Some(ks) = keys.get_mut(0..sz + 1) {
                     *size = (sz + 1) as u8;
                     slice_insert(ks, index, key);
-                    slice_insert(&mut vals[0..=sz], index, value);
+                    slice_insert(&mut vals[0..sz + 1], index, value);
                     true
                 } else {
                     false
                 }
             }
             _ => panic!("Expected leaf node"),
         }
     }
@@ -577,17 +577,17 @@ where
             }
             NodeData::Free { next: Some(n) } => write!(f, "[ free -> {} ]", n),
             NodeData::Free { next: None } => write!(f, "[ free ]"),
         }
     }
 }
 
 #[cfg(test)]
-mod tests {
+mod test {
     use super::*;
     use std::mem;
     use std::string::ToString;
 
     // Forest impl for a set implementation.
     struct TF();
 
     impl Forest for TF {
--- a/third_party/rust/cranelift-bforest/src/path.rs
+++ b/third_party/rust/cranelift-bforest/src/path.rs
@@ -698,17 +698,17 @@ impl<F: Forest> fmt::Display for Path<F>
                 write!(f, "--{}[{}]", self.node[i], self.entry[i])?;
             }
             Ok(())
         }
     }
 }
 
 #[cfg(test)]
-mod tests {
+mod test {
     use super::super::{Forest, NodeData, NodePool};
     use super::*;
     use std::cmp::Ordering;
 
     struct TC();
 
     impl Comparator<i32> for TC {
         fn cmp(&self, a: i32, b: i32) -> Ordering {
--- a/third_party/rust/cranelift-bforest/src/pool.rs
+++ b/third_party/rust/cranelift-bforest/src/pool.rs
@@ -85,17 +85,17 @@ impl<F: Forest> NodePool<F> {
     {
         use entity::SparseSet;
         use std::borrow::Borrow;
         use std::cmp::Ordering;
         use std::vec::Vec;
 
         // The root node can't be an inner node with just a single sub-tree. It should have been
         // pruned.
-        if let NodeData::Inner { size, .. } = self[node] {
+        if let &NodeData::Inner { size, .. } = &self[node] {
             assert!(size > 0, "Root must have more than one sub-tree");
         }
 
         let mut done = SparseSet::new();
         let mut todo = Vec::new();
 
         // Todo-list entries are:
         // 1. Optional LHS key which must be <= all node entries.
--- a/third_party/rust/cranelift-bforest/src/set.rs
+++ b/third_party/rust/cranelift-bforest/src/set.rs
@@ -202,35 +202,38 @@ where
 }
 
 impl<'a, K, C> SetCursor<'a, K, C>
 where
     K: Copy,
     C: Comparator<K>,
 {
     /// Create a cursor with a default (invalid) location.
-    fn new(container: &'a mut Set<K>, forest: &'a mut SetForest<K>, comp: &'a C) -> Self {
-        Self {
+    fn new(
+        container: &'a mut Set<K>,
+        forest: &'a mut SetForest<K>,
+        comp: &'a C,
+    ) -> SetCursor<'a, K, C> {
+        SetCursor {
             root: &mut container.root,
             pool: &mut forest.nodes,
             comp,
             path: Path::default(),
         }
     }
 
     /// Is this cursor pointing to an empty set?
     pub fn is_empty(&self) -> bool {
         self.root.is_none()
     }
 
     /// Move cursor to the next element and return it.
     ///
     /// If the cursor reaches the end, return `None` and leave the cursor at the off-the-end
     /// position.
-    #[cfg_attr(feature = "cargo-clippy", allow(should_implement_trait))]
     pub fn next(&mut self) -> Option<K> {
         self.path.next(self.pool).map(|(k, _)| k)
     }
 
     /// Move cursor to the previous element and return it.
     ///
     /// If the cursor is already pointing at the first element, leave it there and return `None`.
     pub fn prev(&mut self) -> Option<K> {
@@ -349,17 +352,17 @@ where
         match self.root.take() {
             Some(root) => Some(self.path.first(root, self.pool).0),
             None => self.path.next(self.pool).map(|(k, _)| k),
         }
     }
 }
 
 #[cfg(test)]
-mod tests {
+mod test {
     use super::super::NodeData;
     use super::*;
     use std::mem;
     use std::vec::Vec;
 
     #[test]
     fn node_size() {
         // check that nodes are cache line sized when keys are 32 bits.
--- 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":"410de243e172b6d8597ca3cf2d2e8da264762966755ccd4d99496ba4b4034a98","LICENSE":"a6c48161a09acc75a0e25503bab66a731eb5fba5392ed4bb4743e4ba5085327a","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/base/mod.rs":"9320dfed2250bdb0347e01862b2ff7bf7db78920dae1719834b374de11131e87","src/base/types.rs":"a3e449db1f515d268f3ad21301740ba415444d399f8433dbc48979f78557f66a","src/cdsl/mod.rs":"1ed81ef8c6bc01384a840fa01f434c20ddd6c90ba10cdc5dc8b39dab7c647a70","src/cdsl/types.rs":"53e9f0e6d9c2cf0321a0c02324c0408fc14b01d1d3c16771f133169d57ff7a19","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_types.rs":"4b6be1877ce80205bdda954a0e7d4c04083d35811f3907619be18475a005eed3","src/lib.rs":"b6fc7d24e86439a5d62a0662865bf937e921fd6607cbabda616445a7219ec2f5","src/srcgen.rs":"3e6874cb3cb1155dc10ee9043b2a7ca4dfc3373d1079a864f931fc54aa325c9d"},"package":"1da3daa0109e7a0b7b322cea666cc223fb6a0d5170e83d23b3d5d2deaddca5f3"}
\ 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,19 @@
 #
 # 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.20.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"
 [badges.maintenance]
 status = "experimental"
 
 [badges.travis-ci]
 repository = "CraneStation/cranelift"
--- a/third_party/rust/cranelift-codegen-meta/LICENSE
+++ b/third_party/rust/cranelift-codegen-meta/LICENSE
@@ -212,9 +212,8 @@ with the conditions of Sections 4(a), 4(
 In addition, if you combine or link compiled forms of this Software with
 software that is licensed under the GPLv2 ("Combined Software") and if a
 court of competent jurisdiction determines that the patent provision (Section
 3), the indemnity provision (Section 9) or other Section of the License
 conflicts with the conditions of the GPLv2, you may retroactively and
 prospectively choose to deem waived or otherwise exclude such Section(s) of
 the License, but only in their entirety and only with respect to the Combined
 Software.
-
deleted file mode 100644
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs
+++ /dev/null
@@ -1,142 +0,0 @@
-use cranelift_entity::PrimaryMap;
-
-use super::regs::{
-    RegBank, RegBankBuilder, RegBankIndex, RegClass, RegClassBuilder, RegClassIndex,
-};
-
-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 fn add_reg_bank(&mut self, builder: RegBankBuilder) -> RegBankIndex {
-        let first_unit = if self.reg_banks.len() == 0 {
-            0
-        } else {
-            let last = &self.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(
-            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 start = builder.start;
-        assert!(start < reg_bank_units);
-
-        let count = if builder.count != 0 {
-            builder.count
-        } else {
-            reg_bank_units / builder.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,
-            reg_class_index,
-            builder.width,
-            builder.bank,
-            builder.toprc,
-            count,
-            start,
-        );
-        self.reg_classes.push(reg_class);
-
-        let reg_bank = self.reg_banks.get_mut(builder.bank).unwrap();
-        reg_bank.classes.push(reg_class_index);
-
-        reg_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() {
-            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_mask = rc1.mask(0);
-                    let rc2_mask = rc2.mask(0);
-
-                    assert!(
-                        rc1.width != rc2.width || rc1_mask != rc2_mask,
-                        "no duplicates"
-                    );
-                    if rc1.width != rc2.width {
-                        continue;
-                    }
-
-                    let mut intersect = Vec::new();
-                    for (a, b) in rc1_mask.iter().zip(rc2_mask.iter()) {
-                        intersect.push(a & b);
-                    }
-                    if intersect == vec![0; intersect.len()] {
-                        continue;
-                    }
-
-                    // 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
-                                .get(*i1)
-                                .unwrap()
-                                .subclasses
-                                .iter()
-                                .find(|x| **x == *i2)
-                                .is_some()
-                        );
-                    }
-                }
-            }
-        }
-    }
-}
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/mod.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/mod.rs
@@ -1,15 +1,13 @@
 //! Cranelift DSL classes.
 //!
 //! This module defines the classes that are used to define Cranelift
-//! instructions and other entities.
+//! instructions and other entitties.
 
-pub mod isa;
-pub mod regs;
 pub mod types;
 
 /// Convert the string `s` to CamelCase.
 fn _camel_case(s: &str) -> String {
     let mut output_chars = String::with_capacity(s.len());
 
     let mut capitalize = true;
     for curr_char in s.chars() {
deleted file mode 100644
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/regs.rs
+++ /dev/null
@@ -1,199 +0,0 @@
-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,
-    pub names: Vec<&'static str>,
-    pub prefix: &'static str,
-    pub pressure_tracking: bool,
-    pub toprcs: Vec<RegClassIndex>,
-    pub classes: Vec<RegClassIndex>,
-}
-
-impl RegBank {
-    pub fn new(
-        name: &'static str,
-        first_unit: u8,
-        units: u8,
-        names: Vec<&'static str>,
-        prefix: &'static str,
-        pressure_tracking: bool,
-    ) -> Self {
-        RegBank {
-            name,
-            first_unit,
-            units,
-            names,
-            prefix,
-            pressure_tracking,
-            toprcs: Vec::new(),
-            classes: Vec::new(),
-        }
-    }
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct RegClassIndex(u32);
-entity_impl!(RegClassIndex);
-
-pub struct RegClass {
-    pub name: &'static str,
-    pub index: RegClassIndex,
-    pub width: u8,
-    pub bank: RegBankIndex,
-    pub toprc: RegClassIndex,
-    pub count: u8,
-    pub start: u8,
-    pub subclasses: Vec<RegClassIndex>,
-}
-
-impl RegClass {
-    pub fn new(
-        name: &'static str,
-        index: RegClassIndex,
-        width: u8,
-        bank: RegBankIndex,
-        toprc: RegClassIndex,
-        count: u8,
-        start: u8,
-    ) -> Self {
-        Self {
-            name,
-            index,
-            width,
-            bank,
-            toprc,
-            count,
-            start,
-            subclasses: Vec::new(),
-        }
-    }
-
-    /// Compute a bit-mask of subclasses, including self.
-    pub fn subclass_mask(&self) -> u64 {
-        let mut m = 1 << self.index.index();
-        for rc in self.subclasses.iter() {
-            m |= 1 << rc.index();
-        }
-        m
-    }
-
-    /// Compute a bit-mask of the register units allocated by this register class.
-    pub fn mask(&self, bank_first_unit: u8) -> Vec<u32> {
-        let mut u = (self.start + bank_first_unit) as usize;
-        let mut out_mask = vec![0, 0, 0];
-        for _ in 0..self.count {
-            out_mask[u / 32] |= 1 << (u % 32);
-            u += self.width as usize;
-        }
-        out_mask
-    }
-}
-
-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,
-}
-
-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);
-
-        Self {
-            name,
-            index,
-            width: 1,
-            bank,
-            toprc: index,
-            count: 0,
-            start: 0,
-        }
-    }
-
-    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,
-            count: stop - start,
-            width: parent.width,
-            start: parent.start + start * parent.width,
-            bank: parent.bank,
-            toprc: parent.toprc,
-            index,
-        }
-    }
-
-    pub fn count(mut self, count: u8) -> Self {
-        self.count = count;
-        self
-    }
-
-    pub fn width(mut self, width: u8) -> Self {
-        self.width = width;
-        self
-    }
-}
-
-pub struct RegBankBuilder {
-    pub name: &'static str,
-    pub units: u8,
-    pub names: Vec<&'static str>,
-    pub prefix: &'static str,
-    pub pressure_tracking: Option<bool>,
-}
-
-impl RegBankBuilder {
-    pub fn new(name: &'static str, prefix: &'static str) -> Self {
-        Self {
-            name,
-            units: 0,
-            names: vec![],
-            prefix,
-            pressure_tracking: None,
-        }
-    }
-    pub fn units(mut self, units: u8) -> Self {
-        self.units = units;
-        self
-    }
-    pub fn names(mut self, names: Vec<&'static str>) -> Self {
-        self.names = names;
-        self
-    }
-    pub fn track_pressure(mut self, track: bool) -> Self {
-        self.pressure_tracking = Some(track);
-        self
-    }
-}
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/types.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/types.rs
@@ -74,29 +74,39 @@ impl ValueType {
         }
     }
 
     /// Find the number of bytes that this type occupies in memory.
     pub fn membytes(&self) -> u64 {
         self.width() / 8
     }
 
+    /// Get the name of this type.
+    pub fn name(&self) -> String {
+        match *self {
+            ValueType::BV(ref b) => b.name(),
+            ValueType::Lane(l) => l.name(),
+            ValueType::Special(s) => s.name(),
+            ValueType::Vector(ref v) => v.name(),
+        }
+    }
+
     /// Find the unique number associated with this type.
     pub fn number(&self) -> Option<u8> {
         match *self {
             ValueType::BV(_) => None,
             ValueType::Lane(l) => Some(l.number()),
             ValueType::Special(s) => Some(s.number()),
             ValueType::Vector(ref v) => Some(v.number()),
         }
     }
 
     /// Return the name of this type for generated Rust source files.
     pub fn _rust_name(&self) -> String {
-        format!("{}{}", _RUST_NAME_PREFIX, self.to_string().to_uppercase())
+        format!("{}{}", _RUST_NAME_PREFIX, self.name().to_uppercase())
     }
 
     /// Return true iff:
     ///     1. self and other have equal number of lanes
     ///     2. each lane in self has at least as many bits as a lane in other
     pub fn _wider_or_equal(&self, rhs: &ValueType) -> bool {
         (self.lane_count() == rhs.lane_count()) && (self.lane_bits() >= rhs.lane_bits())
     }
@@ -104,22 +114,17 @@ impl ValueType {
     /// Return the total number of bits of an instance of this type.
     pub fn width(&self) -> u64 {
         self.lane_count() * self.lane_bits()
     }
 }
 
 impl fmt::Display for ValueType {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            ValueType::BV(ref b) => b.fmt(f),
-            ValueType::Lane(l) => l.fmt(f),
-            ValueType::Special(s) => s.fmt(f),
-            ValueType::Vector(ref v) => v.fmt(f),
-        }
+        write!(f, "{}", self.name())
     }
 }
 
 /// Create a ValueType from a given bitvector type.
 impl From<BVType> for ValueType {
     fn from(bv: BVType) -> Self {
         ValueType::BV(bv)
     }
@@ -151,18 +156,18 @@ impl From<VectorType> for ValueType {
 pub enum LaneType {
     BoolType(base_types::Bool),
     FloatType(base_types::Float),
     IntType(base_types::Int),
 }
 
 impl LaneType {
     /// Return a string containing the documentation comment for this lane type.
-    pub fn doc(self) -> String {
-        match self {
+    pub fn doc(&self) -> String {
+        match *self {
             LaneType::BoolType(_) => format!("A boolean type with {} bits.", self.lane_bits()),
             LaneType::FloatType(base_types::Float::F32) => String::from(
                 "A 32-bit floating point type represented in the IEEE 754-2008
                 *binary32* interchange format. This corresponds to the :c:type:`float`
                 type in most C implementations.",
             ),
             LaneType::FloatType(base_types::Float::F64) => String::from(
                 "A 64-bit floating point type represented in the IEEE 754-2008
@@ -175,52 +180,51 @@ impl LaneType {
                 self.lane_bits(),
                 self.lane_bits()
             ),
             LaneType::IntType(_) => format!("An integer type with {} bits.", self.lane_bits()),
         }
     }
 
     /// Return the number of bits in a lane.
-    pub fn lane_bits(self) -> u64 {
-        match self {
+    pub fn lane_bits(&self) -> u64 {
+        match *self {
             LaneType::BoolType(ref b) => *b as u64,
             LaneType::FloatType(ref f) => *f as u64,
             LaneType::IntType(ref i) => *i as u64,
         }
     }
 
+    /// Get the name of this lane type.
+    pub fn name(&self) -> String {
+        match *self {
+            LaneType::BoolType(_) => format!("b{}", self.lane_bits()),
+            LaneType::FloatType(_) => format!("f{}", self.lane_bits()),
+            LaneType::IntType(_) => format!("i{}", self.lane_bits()),
+        }
+    }
+
     /// Find the unique number associated with this lane type.
-    pub fn number(self) -> u8 {
-        LANE_BASE + match self {
+    pub fn number(&self) -> u8 {
+        LANE_BASE + match *self {
             LaneType::BoolType(base_types::Bool::B1) => 0,
             LaneType::BoolType(base_types::Bool::B8) => 1,
             LaneType::BoolType(base_types::Bool::B16) => 2,
             LaneType::BoolType(base_types::Bool::B32) => 3,
             LaneType::BoolType(base_types::Bool::B64) => 4,
             LaneType::IntType(base_types::Int::I8) => 5,
             LaneType::IntType(base_types::Int::I16) => 6,
             LaneType::IntType(base_types::Int::I32) => 7,
             LaneType::IntType(base_types::Int::I64) => 8,
             LaneType::FloatType(base_types::Float::F32) => 9,
             LaneType::FloatType(base_types::Float::F64) => 10,
         }
     }
 }
 
-impl fmt::Display for LaneType {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            LaneType::BoolType(_) => write!(f, "b{}", self.lane_bits()),
-            LaneType::FloatType(_) => write!(f, "f{}", self.lane_bits()),
-            LaneType::IntType(_) => write!(f, "i{}", self.lane_bits()),
-        }
-    }
-}
-
 impl fmt::Debug for LaneType {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let inner_msg = format!("bits={}", self.lane_bits());
         write!(
             f,
             "{}",
             match *self {
                 LaneType::BoolType(_) => format!("BoolType({})", inner_msg),
@@ -291,63 +295,62 @@ impl Iterator for LaneTypeIterator {
 /// and a positive number of lanes.
 pub struct VectorType {
     base: LaneType,
     lanes: u64,
 }
 
 impl VectorType {
     /// Initialize a new integer type with `n` bits.
-    pub fn new(base: LaneType, lanes: u64) -> Self {
-        Self { base, lanes }
+    pub fn new(base: LaneType, lanes: u64) -> VectorType {
+        VectorType { base, lanes }
     }
 
     /// Return a string containing the documentation comment for this vector type.
     pub fn doc(&self) -> String {
         format!(
             "A SIMD vector with {} lanes containing a `{}` each.",
             self.lane_count(),
-            self.base
+            self.base.name()
         )
     }
 
     /// Return the number of bits in a lane.
     pub fn lane_bits(&self) -> u64 {
         self.base.lane_bits()
     }
 
     /// Return the number of lanes.
     pub fn lane_count(&self) -> u64 {
         self.lanes
     }
 
+    /// Get the name of this vector type.
+    pub fn name(&self) -> String {
+        format!("{}x{}", self.base.name(), self.lane_count())
+    }
+
     /// Find the unique number associated with this vector type.
     ///
     /// Vector types are encoded with the lane type in the low 4 bits and
     /// log2(lanes) in the high 4 bits, giving a range of 2-256 lanes.
     pub fn number(&self) -> u8 {
         let lanes_log_2: u32 = 63 - self.lane_count().leading_zeros();
         let base_num = u32::from(self.base.number());
         let num = (lanes_log_2 << 4) + base_num;
         num as u8
     }
 }
 
-impl fmt::Display for VectorType {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}x{}", self.base, self.lane_count())
-    }
-}
-
 impl fmt::Debug for VectorType {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(
             f,
             "VectorType(base={}, lanes={})",
-            self.base,
+            self.base.name(),
             self.lane_count()
         )
     }
 }
 
 /// A flat bitvector type. Used for semantics description only.
 pub struct BVType {
     bits: u64,
@@ -363,21 +366,20 @@ impl BVType {
     pub fn doc(&self) -> String {
         format!("A bitvector type with {} bits.", self.bits)
     }
 
     /// Return the number of bits in a lane.
     pub fn lane_bits(&self) -> u64 {
         self.bits
     }
-}
 
-impl fmt::Display for BVType {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "bv{}", self.bits)
+    /// Get the name of this bitvector type.
+    pub fn name(&self) -> String {
+        format!("bv{}", self.bits)
     }
 }
 
 impl fmt::Debug for BVType {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "BVType(bits={})", self.lane_bits())
     }
 }
@@ -387,61 +389,60 @@ impl fmt::Debug for BVType {
 /// Special types cannot be used to form vectors.
 #[derive(Clone, Copy)]
 pub enum SpecialType {
     Flag(base_types::Flag),
 }
 
 impl SpecialType {
     /// Return a string containing the documentation comment for this special type.
-    pub fn doc(self) -> String {
-        match self {
+    pub fn doc(&self) -> String {
+        match *self {
             SpecialType::Flag(base_types::Flag::IFlags) => String::from(
                 "CPU flags representing the result of an integer comparison. These flags
                 can be tested with an :type:`intcc` condition code.",
             ),
             SpecialType::Flag(base_types::Flag::FFlags) => String::from(
                 "CPU flags representing the result of a floating point comparison. These
                 flags can be tested with a :type:`floatcc` condition code.",
             ),
         }
     }
 
     /// Return the number of bits in a lane.
-    pub fn lane_bits(self) -> u64 {
-        match self {
+    pub fn lane_bits(&self) -> u64 {
+        match *self {
             SpecialType::Flag(_) => 0,
         }
     }
 
+    /// Get the name of this special type.
+    pub fn name(&self) -> String {
+        match *self {
+            SpecialType::Flag(base_types::Flag::IFlags) => "iflags".to_string(),
+            SpecialType::Flag(base_types::Flag::FFlags) => "fflags".to_string(),
+        }
+    }
+
     /// Find the unique number associated with this special type.
-    pub fn number(self) -> u8 {
-        match self {
+    pub fn number(&self) -> u8 {
+        match *self {
             SpecialType::Flag(base_types::Flag::IFlags) => 1,
             SpecialType::Flag(base_types::Flag::FFlags) => 2,
         }
     }
 }
 
-impl fmt::Display for SpecialType {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            SpecialType::Flag(base_types::Flag::IFlags) => write!(f, "iflags"),
-            SpecialType::Flag(base_types::Flag::FFlags) => write!(f, "fflags"),
-        }
-    }
-}
-
 impl fmt::Debug for SpecialType {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(
             f,
             "{}",
             match *self {
-                SpecialType::Flag(_) => format!("FlagsType({})", self),
+                SpecialType::Flag(_) => format!("FlagsType({})", self.name()),
             }
         )
     }
 }
 
 impl From<base_types::Flag> for SpecialType {
     fn from(f: base_types::Flag) -> Self {
         SpecialType::Flag(f)
deleted file mode 100644
--- a/third_party/rust/cranelift-codegen-meta/src/gen_registers.rs
+++ /dev/null
@@ -1,140 +0,0 @@
-use cdsl::isa::TargetIsa;
-use cdsl::regs::{RegBank, RegClass};
-use cranelift_entity::EntityRef;
-use error;
-use srcgen::Formatter;
-
-fn gen_regbank(fmt: &mut Formatter, reg_bank: &RegBank) {
-    let names = if reg_bank.names.len() > 0 {
-        format!(r#""{}""#, reg_bank.names.join(r#"", ""#))
-    } else {
-        "".to_string()
-    };
-    fmt.line("RegBank {");
-    fmt.indent(|fmt| {
-        fmt.line(&format!(r#"name: "{}","#, reg_bank.name));
-        fmt.line(&format!("first_unit: {},", reg_bank.first_unit));
-        fmt.line(&format!("units: {},", reg_bank.units));
-        fmt.line(&format!("names: &[{}],", names));
-        fmt.line(&format!(r#"prefix: "{}","#, reg_bank.prefix));
-        fmt.line(&format!("first_toprc: {},", reg_bank.toprcs[0].index()));
-        fmt.line(&format!("num_toprcs: {},", reg_bank.toprcs.len()));
-        fmt.line(&format!(
-            "pressure_tracking: {},",
-            if reg_bank.pressure_tracking {
-                "true"
-            } else {
-                "false"
-            }
-        ));
-    });
-    fmt.line("},");
-}
-
-fn gen_regclass(isa: &TargetIsa, reg_class: &RegClass, fmt: &mut Formatter) {
-    let reg_bank = isa.reg_banks.get(reg_class.bank).unwrap();
-
-    let mask: Vec<String> = reg_class
-        .mask(reg_bank.first_unit)
-        .iter()
-        .map(|x| format!("0x{:08x}", x))
-        .collect();
-    let mask = mask.join(", ");
-
-    fmt.line(&format!(
-        "pub static {}_DATA: RegClassData = RegClassData {{",
-        reg_class.name
-    ));
-    fmt.indent(|fmt| {
-        fmt.line(&format!(r#"name: "{}","#, reg_class.name));
-        fmt.line(&format!("index: {},", reg_class.index.index()));
-        fmt.line(&format!("width: {},", reg_class.width));
-        fmt.line(&format!("bank: {},", reg_class.bank.index()));
-        fmt.line(&format!("toprc: {},", reg_class.toprc.index()));
-        fmt.line(&format!(
-            "first: {},",
-            reg_bank.first_unit + reg_class.start
-        ));
-        fmt.line(&format!("subclasses: {:#x},", reg_class.subclass_mask()));
-        fmt.line(&format!("mask: [{}],", mask));
-        fmt.line("info: &INFO,");
-    });
-    fmt.line("};");
-    fmt.line("#[allow(dead_code)]");
-    fmt.line(&format!(
-        "pub static {}: RegClass = &{}_DATA;",
-        reg_class.name, reg_class.name
-    ));
-}
-
-fn gen_regbank_units(reg_bank: &RegBank, fmt: &mut Formatter) {
-    for unit in 0..reg_bank.units {
-        let v = unit + reg_bank.first_unit;
-        if (unit as usize) < reg_bank.names.len() {
-            fmt.line(&format!("{} = {},", reg_bank.names[unit as usize], v));
-            continue;
-        }
-        fmt.line(&format!("{}{} = {},", reg_bank.prefix, unit, v));
-    }
-}
-
-fn gen_isa(isa: &TargetIsa, fmt: &mut Formatter) -> Result<(), error::Error> {
-    // Emit RegInfo.
-    fmt.line("pub static INFO: RegInfo = RegInfo {");
-
-    fmt.indent(|fmt| {
-        fmt.line("banks: &[");
-        // Bank descriptors.
-        fmt.indent(|fmt| {
-            for reg_bank in isa.reg_banks.values() {
-                gen_regbank(fmt, &reg_bank);
-            }
-        });
-        fmt.line("],");
-        // References to register classes.
-        fmt.line("classes: &[");
-        fmt.indent(|fmt| {
-            for reg_class in isa.reg_classes.values() {
-                fmt.line(&format!("&{}_DATA,", reg_class.name));
-            }
-        });
-        fmt.line("],");
-    });
-    fmt.line("};");
-
-    // Register class descriptors.
-    for rc in isa.reg_classes.values() {
-        gen_regclass(&isa, rc, fmt);
-    }
-
-    // Emit constants for all the register units.
-    fmt.line("#[allow(dead_code, non_camel_case_types)]");
-    fmt.line("#[derive(Clone, Copy)]");
-    fmt.line("pub enum RU {");
-    fmt.indent(|fmt| {
-        for reg_bank in isa.reg_banks.values() {
-            gen_regbank_units(reg_bank, fmt);
-        }
-    });
-    fmt.line("}");
-
-    // Emit Into conversion for the RU class.
-    fmt.line("impl Into<RegUnit> for RU {");
-    fmt.indent(|fmt| {
-        fmt.line("fn into(self) -> RegUnit {");
-        fmt.indent(|fmt| {
-            fmt.line("self as RegUnit");
-        });
-        fmt.line("}")
-    });
-    fmt.line("}");
-
-    Ok(())
-}
-
-pub fn generate(isa: TargetIsa, base_filename: &str, out_dir: &str) -> Result<(), error::Error> {
-    let mut fmt = Formatter::new();
-    gen_isa(&isa, &mut fmt)?;
-    fmt.update_file(&format!("{}-{}.rs", base_filename, isa.name), out_dir)?;
-    Ok(())
-}
--- a/third_party/rust/cranelift-codegen-meta/src/gen_types.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/gen_types.rs
@@ -8,17 +8,17 @@
 //! type numbering.
 
 use cdsl::types as cdsl_types;
 use error;
 use srcgen;
 
 /// Emit a constant definition of a single value type.
 fn emit_type(ty: &cdsl_types::ValueType, fmt: &mut srcgen::Formatter) -> Result<(), error::Error> {
-    let name = ty.to_string().to_uppercase();
+    let name = ty.name().to_uppercase();
     let number = ty.number().ok_or_else(|| {
         error::Error::with_msg(format!(
             "Could not emit type `{}` which has no number.",
             name
         ))
     })?;
 
     let definition = format!("pub const {}: Type = Type({:#x});\n", name, number);
@@ -42,17 +42,18 @@ fn emit_vectors(bits: u64, fmt: &mut src
     }
 
     Ok(())
 }
 
 /// Emit types using the given formatter object.
 fn emit_types(fmt: &mut srcgen::Formatter) -> Result<(), error::Error> {
     // Emit all of the special types, such as types for CPU flags.
-    for spec in cdsl_types::ValueType::all_special_types().map(cdsl_types::ValueType::from) {
+    for spec in cdsl_types::ValueType::all_special_types().map(|ty| cdsl_types::ValueType::from(ty))
+    {
         emit_type(&spec, fmt)?;
     }
 
     // Emit all of the lane types, such integers, floats, and booleans.
     for ty in cdsl_types::ValueType::all_lane_types().map(cdsl_types::ValueType::from) {
         emit_type(&ty, fmt)?;
     }
 
deleted file mode 100644
--- a/third_party/rust/cranelift-codegen-meta/src/isa/arm32/mod.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-use cdsl::regs::{RegBankBuilder, RegClassBuilder};
-use isa;
-
-pub fn define() -> isa::TargetIsa {
-    let mut isa = isa::TargetIsa::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)
-        .track_pressure(true);
-    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);
-    isa.add_reg_class(builder);
-
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "D", float_regs).width(2);
-    isa.add_reg_class(builder);
-
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "Q", float_regs).width(4);
-    isa.add_reg_class(builder);
-
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "GPR", int_regs);
-    isa.add_reg_class(builder);
-
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FLAG", flag_reg);
-    isa.add_reg_class(builder);
-
-    isa
-}
deleted file mode 100644
--- a/third_party/rust/cranelift-codegen-meta/src/isa/arm64/mod.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-use cdsl::regs::{RegBankBuilder, RegClassBuilder};
-use isa;
-
-pub fn define() -> isa::TargetIsa {
-    let mut isa = isa::TargetIsa::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);
-
-    let builder = RegBankBuilder::new("FloatRegs", "v")
-        .units(32)
-        .track_pressure(true);
-    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);
-    isa.add_reg_class(builder);
-
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FPR", float_regs);
-    isa.add_reg_class(builder);
-
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FLAG", flag_reg);
-    isa.add_reg_class(builder);
-
-    isa
-}
deleted file mode 100644
--- a/third_party/rust/cranelift-codegen-meta/src/isa/mod.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-use cdsl::isa::TargetIsa;
-use std::fmt;
-
-mod arm32;
-mod arm64;
-mod riscv;
-mod x86;
-
-/// Represents known ISA target.
-#[derive(Copy, Clone)]
-pub enum Isa {
-    Riscv,
-    X86,
-    Arm32,
-    Arm64,
-}
-
-impl Isa {
-    /// Creates isa target using name.
-    pub fn new(name: &str) -> Option<Self> {
-        Isa::all()
-            .iter()
-            .cloned()
-            .filter(|isa| isa.to_string() == name)
-            .next()
-    }
-
-    /// Creates isa target from arch.
-    pub fn from_arch(arch: &str) -> Option<Isa> {
-        Isa::all()
-            .iter()
-            .cloned()
-            .filter(|isa| isa.is_arch_applicable(arch))
-            .next()
-    }
-
-    /// Returns all supported isa targets.
-    pub fn all() -> [Isa; 4] {
-        [Isa::Riscv, Isa::X86, Isa::Arm32, Isa::Arm64]
-    }
-
-    /// Checks if arch is applicable for the isa target.
-    fn is_arch_applicable(&self, arch: &str) -> bool {
-        match *self {
-            Isa::Riscv => arch == "riscv",
-            Isa::X86 => ["x86_64", "i386", "i586", "i686"].contains(&arch),
-            Isa::Arm32 => arch.starts_with("arm") || arch.starts_with("thumb"),
-            Isa::Arm64 => arch == "aarch64",
-        }
-    }
-}
-
-impl fmt::Display for Isa {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Isa::Riscv => write!(f, "riscv"),
-            Isa::X86 => write!(f, "x86"),
-            Isa::Arm32 => write!(f, "arm32"),
-            Isa::Arm64 => write!(f, "arm64"),
-        }
-    }
-}
-
-pub fn define_all() -> Vec<TargetIsa> {
-    let isas = vec![
-        riscv::define(),
-        arm32::define(),
-        arm64::define(),
-        x86::define(),
-    ];
-    for isa in isas.iter() {
-        isa.check();
-    }
-    isas
-}
deleted file mode 100644
--- a/third_party/rust/cranelift-codegen-meta/src/isa/riscv/mod.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-use cdsl::regs::{RegBankBuilder, RegClassBuilder};
-use isa;
-
-pub fn define() -> isa::TargetIsa {
-    let mut isa = isa::TargetIsa::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);
-    isa.add_reg_class(builder);
-
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FPR", float_regs);
-    isa.add_reg_class(builder);
-
-    isa
-}
deleted file mode 100644
--- a/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-use cdsl::regs::{RegBankBuilder, RegClassBuilder};
-use isa;
-
-pub fn define() -> isa::TargetIsa {
-    let mut isa = isa::TargetIsa::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")
-        .units(16)
-        .track_pressure(true);
-    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 gpr = isa.add_reg_class(builder);
-
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FPR", float_regs);
-    let fpr = isa.add_reg_class(builder);
-
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FLAG", flag_reg);
-    isa.add_reg_class(builder);
-
-    let builder = RegClassBuilder::subclass_of(&mut isa, "GPR8", gpr, 0, 8);
-    let gpr8 = isa.add_reg_class(builder);
-
-    let builder = RegClassBuilder::subclass_of(&mut isa, "ABCD", gpr8, 0, 4);
-    isa.add_reg_class(builder);
-
-    let builder = RegClassBuilder::subclass_of(&mut isa, "FPR8", fpr, 0, 8);
-    isa.add_reg_class(builder);
-
-    isa
-}
--- a/third_party/rust/cranelift-codegen-meta/src/lib.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/lib.rs
@@ -1,11 +1,6 @@
-#[macro_use]
-extern crate cranelift_entity;
-
 pub mod error;
-pub mod gen_registers;
 pub mod gen_types;
-pub mod isa;
 
 mod base;
 mod cdsl;
 mod srcgen;
--- a/third_party/rust/cranelift-codegen-meta/src/srcgen.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/srcgen.rs
@@ -7,64 +7,75 @@ use std::collections::{BTreeMap, HashSet
 use std::fs;
 use std::io::Write;
 use std::path;
 
 use error;
 
 static SHIFTWIDTH: usize = 4;
 
+struct _IndentedScope {
+    fmt: Formatter,
+    after: Option<String>,
+}
+
+impl _IndentedScope {
+    fn _enter(&mut self) {
+        self.fmt._indent_push();
+    }
+
+    fn _exit(&mut self) {
+        self.fmt._indent_pop();
+        if let Some(ref s) = self.after {
+            self.fmt.line(&s);
+        }
+    }
+}
+
 pub struct Formatter {
     indent: usize,
     lines: Vec<String>,
 }
 
 impl Formatter {
     /// Source code formatter class. Used to collect source code to be written
     /// to a file, and keep track of indentation.
-    pub fn new() -> Self {
-        Self {
+    pub fn new() -> Formatter {
+        Formatter {
             indent: 0,
             lines: Vec::new(),
         }
     }
 
     /// Increase current indentation level by one.
-    pub fn indent_push(&mut self) {
+    pub fn _indent_push(&mut self) {
         self.indent += 1;
     }
 
     /// Decrease indentation by one level.
-    pub fn indent_pop(&mut self) {
+    pub fn _indent_pop(&mut self) {
         assert!(self.indent > 0, "Already at top level indentation");
         self.indent -= 1;
     }
 
-    pub fn indent<T, F: FnOnce(&mut Formatter) -> T>(&mut self, f: F) -> T {
-        self.indent_push();
-        let ret = f(self);
-        self.indent_pop();
-        ret
-    }
-
     /// Get the current whitespace indentation in the form of a String.
     fn get_indent(&self) -> String {
         if self.indent == 0 {
             String::new()
         } else {
             format!("{:-1$}", " ", self.indent * SHIFTWIDTH)
         }
     }
 
     /// Get a string containing whitespace outdented one level. Used for
     /// lines of code that are inside a single indented block.
     fn _get_outdent(&mut self) -> String {
-        self.indent_push();
+        self._indent_push();
         let s = self.get_indent();
-        self.indent_pop();
+        self._indent_pop();
         s
     }
 
     /// Add an indented line.
     pub fn line(&mut self, contents: &str) {
         let indented_line = format!("{}{}\n", self.get_indent(), contents);
         self.lines.push(indented_line);
     }
@@ -87,16 +98,23 @@ impl Formatter {
 
         for l in self.lines.iter().map(|l| l.as_bytes()) {
             f.write_all(l)?;
         }
 
         Ok(())
     }
 
+    /// Return a scope object for use with a `with` statement.
+    /// The optional `before` and `after` parameters are surrounding lines
+    /// which are *not* indented.
+    fn _indented(&self, _before: Option<&str>, _after: Option<&str>) -> _IndentedScope {
+        unimplemented!();
+    }
+
     /// Add one or more lines after stripping common indentation.
     pub fn _multi_line(&mut self, s: &str) {
         parse_multiline(s).into_iter().for_each(|l| self.line(&l));
     }
 
     /// Add a comment line.
     pub fn _comment(&mut self, s: &str) {
         let commented_line = format!("// {}", s);
@@ -135,16 +153,17 @@ fn parse_multiline(s: &str) -> Vec<Strin
     let expanded_tab = format!("{:-1$}", " ", SHIFTWIDTH);
     let lines: Vec<String> = s.lines().map(|l| l.replace("\t", &expanded_tab)).collect();
 
     // Determine minimum indentation, ignoring the first line.
     let indent = lines
         .iter()
         .skip(1)
         .map(|l| l.len() - l.trim_left().len())
+        .filter(|&i| i > 0)
         .min();
 
     // Strip off leading blank lines.
     let mut lines_iter = lines.iter().skip_while(|l| l.is_empty());
     let mut trimmed = Vec::with_capacity(lines.len());
 
     // Remove indentation (first line is special)
     if let Some(s) = lines_iter.next().map(|l| l.trim()).map(|l| l.to_string()) {
@@ -233,19 +252,19 @@ mod srcgen_tests {
         let output = parse_multiline(input);
         assert_eq!(output, expected);
     }
 
     #[test]
     fn formatter_basic_example_works() {
         let mut fmt = Formatter::new();
         fmt.line("Hello line 1");
-        fmt.indent_push();
+        fmt._indent_push();
         fmt._comment("Nested comment");
-        fmt.indent_pop();
+        fmt._indent_pop();
         fmt.line("Back home again");
         let expected_lines = vec![
             "Hello line 1\n",
             "    // Nested comment\n",
             "Back home again\n",
         ];
         assert_eq!(fmt.lines, expected_lines);
     }
@@ -253,19 +272,19 @@ mod srcgen_tests {
     #[test]
     fn get_indent_works() {
         let mut fmt = Formatter::new();
         let expected_results = vec!["", "    ", "        ", ""];
 
         let actual_results = Vec::with_capacity(4);
         (0..3).for_each(|_| {
             fmt.get_indent();
-            fmt.indent_push();
+            fmt._indent_push();
         });
-        (0..3).for_each(|_| fmt.indent_pop());
+        (0..3).for_each(|_| fmt._indent_pop());
         fmt.get_indent();
 
         actual_results
             .into_iter()
             .zip(expected_results.into_iter())
             .for_each(|(actual, expected): (String, &str)| assert_eq!(&actual, expected));
     }
 
@@ -276,17 +295,17 @@ mod srcgen_tests {
         let expected_lines = vec!["pub const example: Type = Type(0x0);\n"];
         assert_eq!(fmt.lines, expected_lines);
     }
 
     #[test]
     fn fmt_can_add_indented_line() {
         let mut fmt = Formatter::new();
         fmt.line("hello");
-        fmt.indent_push();
+        fmt._indent_push();
         fmt.line("world");
         let expected_lines = vec!["hello\n", "    world\n"];
         assert_eq!(fmt.lines, expected_lines);
     }
 
     #[test]
     fn fmt_can_add_doc_comments() {
         let mut fmt = Formatter::new();
--- 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":"7d2b91fa0c8cba9be977b41f792fd41646183b455b8736f1c617fa55c7abf454","LICENSE":"a6c48161a09acc75a0e25503bab66a731eb5fba5392ed4bb4743e4ba5085327a","README.md":"e5127227a7db4a8aa92fa6613ed71801025790e696bb41b0323fb7f3c6f7495a","build.rs":"ea5ff1e3ebe7f6f06f9c39c2458268fea3aceb8121d31a3ad311b391631e8408","meta-python/base/__init__.py":"4fac8bb055541dc964383bb04223bae6dfbfe348abf5e23f83655966cbb4aa8f","meta-python/base/entities.py":"0e146dd56dfb93cac88f9557a3501c9804cff584c2723db27435842bb5e2a1b7","meta-python/base/formats.py":"791e5321fa5030a8a247f3d6e2e395e013e477be3e08059b2ccda66cece96bf9","meta-python/base/immediates.py":"f42682d86bda7b569ec2fc2debd9036355999e61caaa9fbf8307e0be8a164814","meta-python/base/instructions.py":"df02d335baf5eba7f1b607b058cf4412cab0c1c81e026cbee923f74146419b77","meta-python/base/legalize.py":"e677e7c97547847731a23fd0fb2a695881beaee6991a7b7a3bb10157c9a17c1c","meta-python/base/predicates.py":"53a5a9a37021a9762f0faec9f9e3c5b713411d47dd9192423cfe0f7a61916809","meta-python/base/semantics.py":"b90cbca9a143676ac37496c83634a66a83360248e4505ff7bda12b0d454efd92","meta-python/base/settings.py":"b59efbf787aeae5117eb89f05fc494b6b84e414e7be360613f30adfee6b3d318","meta-python/base/types.py":"98bdfe14ef94090ba8dfbe3e3ca1135e4e2ece4e25d6bac4d15dc72d9a1e5d21","meta-python/build.py":"7aab54a39b555fec3eb9fd771cb2d9467708e3402f8411e88cf11cb32d0c44ca","meta-python/cdsl/__init__.py":"b531693b8228553ca8bd07e1dcd1aa5855f1ad3741b431d758fc27fdd162b024","meta-python/cdsl/ast.py":"552a9a74aa19031ec730912a1e83e405738de9c4df0ddc7fd811b4bd8c2f40fc","meta-python/cdsl/formats.py":"fedfeaec754b40d6a9cc92b827976782c615d8eab1c7f47f6b47510cbef585f4","meta-python/cdsl/instructions.py":"9ba1b30ed90f2192845e22093179338f2f47e6fe7e15c583cbda2879c006a751","meta-python/cdsl/isa.py":"92bd937c833015f4808f7550f517c4cbc09c6c2e16ecc663d33abb551d124020","meta-python/cdsl/operands.py":"e24914eae4059b88781bf5a5d7a14ecf98b10a701ed6cf6e88d15981b2ccbfdf","meta-python/cdsl/predicates.py":"8663e3b797c7a7313e940456be1d90c3c3cec022aa523b9a9e76fa17e7af51d3","meta-python/cdsl/registers.py":"a8cee541134d34d732926a43f31eb388f684974103d1b1a9645164b0446a3b90","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":"06ac251260a6623d2d58ffbc94529d5faf45a49e5b9c7ec575a84201eb18bece","meta-python/cdsl/test_typevar.py":"714b2d564af1a843629279501436d681cd6590d1988b59e9f50ec940506538bb","meta-python/cdsl/test_xform.py":"ddb6633c7941bbf68570701cb887a81d6b4b27f4bc45eabccf2ce287ad9b77e9","meta-python/cdsl/ti.py":"60019250844ce6b1cdc197f78e02a037223aa65eb18cfb5f17369d84d93d4fe7","meta-python/cdsl/types.py":"d332fe96c0be47d33f651b6cb6339a8c91e7e170832ec2f27b8a5b02bd549a6a","meta-python/cdsl/typevar.py":"a1a405149343011255ff69edb44cf5f960559d1351b6ec07cf6d0bd668d87c4b","meta-python/cdsl/xform.py":"b9db7dd9a4b32e2cfc34def1d2e3213f1fb250a0f66b3aca2c1f30129437d4b6","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":"73a216007ec6e90acf74f51657516de0465fbb692d08c9db0885b1c2aec502a9","meta-python/gen_instr.py":"e9f71675ebc82ee6151c1d671449418939f1e258a504f9b16bebe799788771df","meta-python/gen_legalizer.py":"187a47f1702e07487fb8a13076aadcf9c2de3e801d367424dc847ff7b0ed70f1","meta-python/gen_registers.py":"cfde66d3d75ac7e647afa5a0a7051f5fc1ac757cf142b497f549e57ceb6ff54b","meta-python/gen_settings.py":"44c231ab8d2aa4f18cbe4fb5a33fb72103503d58f5af22c7b545eeffbf97da79","meta-python/gen_types.py":"0cff50db1ecebc2ba67d7e02ed6ab975713d460083cb03ee8a9bc58d021e3ca2","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":"bfc32c901e3e5f46cb6d50167736b967862d2e4f54535986ce20b38f933e4588","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":"b964bd028aedc5422e1ef3a088f456dac4feb10e6d310858cee9245479fa3547","meta-python/isa/x86/instructions.py":"530cde78e6b9f6e4ea2192985f4c5c77a987cdc19001d50fb47fa8e36a62f52e","meta-python/isa/x86/legalize.py":"1375ded072c29459e7c0e40ecb02f28d5395d9d8c603eb70e338b2bf2991c9cd","meta-python/isa/x86/recipes.py":"f92e8b3007198bb85139172d2d19fb5b3462d92012282e1877b05e1c07673332","meta-python/isa/x86/registers.py":"60a9f42fede6330cd7ef001d85ece9f7095cbc20fc4004de65a3dd9972236293","meta-python/isa/x86/settings.py":"d779a768475cf00c2a8d3ddb5cd0a70ce34662e0ebb52ee26a7e1a495ec41aa2","meta-python/mypy.ini":"5ec2f7cc0bbc4fd0435643d6b72e715bd9568a3a0fe14c043f9e559c405b66fb","meta-python/semantics/__init__.py":"3df36e0a986fd90d0b69740b02671251ecd2853873998dcb6d379894a4f9460b","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":"85adb793c5eb5711aca64534225eb4fc98ae0c79cea42dd6d86e9c193dec97cc","src/binemit/mod.rs":"95ed53492873dfbed44cd185085740ab20f9e7543a26855f0466e7a607f6ff54","src/binemit/relaxation.rs":"dd8b50f32ba9688c7f6d0e2957c120192e3d26d8301db405038ab1ece4777746","src/binemit/shrink.rs":"6b5622701f4496c6fc540555236716749f053e126102f73e63b03f3306e50670","src/bitset.rs":"67fd02dd2acb9af73e45426e5cab1d2a74d568a11d11ee17ae6a4421f96cf741","src/cfg_printer.rs":"1bbe85c44002222c38a54f1c741f99e4ba6eb1e90e377907e62504ede847ef93","src/constant_hash.rs":"493cdf8f607eab01bb52f93d616fb6190c7c86d3a02e530b0ced30993d4bfda0","src/context.rs":"29222884fd459d3d056ab1f490165a7bb8b9d27fe1ed297fd8f06a6ad7c9f46f","src/cursor.rs":"7dd7cc957c0d1ad0850162b6a0d3f13b8f0d8cc00e22d481458df7b2486611a7","src/dbg.rs":"bae915e1f7544f725817b368aed00a6aaa9e394a454dc847d65ad44e54d78cb9","src/dce.rs":"6d015824ae0325f01bb523606d7e15dd5feeb72a75b947f40385feeba94555c8","src/divconst_magic_numbers.rs":"eac50e2353e17ab6f7d1da3bd8e0e8dc9e3122a160efba594d407eb6a8936cc7","src/dominator_tree.rs":"595031c03afa61020b26eb071a26d6c4949361f5e4e0e8b516e5a04adf200fe3","src/flowgraph.rs":"337341ed7d9070e46fc0048f1069a95c985ffe4b405f9a10e606a38b5e05851f","src/fx.rs":"2fb53f141b3e6be1882a1e4afac4bc607ce694f045d9329ee823e0aca415898e","src/ir/builder.rs":"740fead2c1986e5f3a836de06b37e6a45188a7d40c64f86c5097624e92c6e9d6","src/ir/condcodes.rs":"5456a25798516245b0923c9e12ae0af5cc98c097fc6f3bc0bf2d7af5008667f7","src/ir/dfg.rs":"0e61ea5a0515a73ae57d7625b0a67d82d6f8b5c0ba6673d1eae0d3b48745edbc","src/ir/entities.rs":"1505347c2baa256b04f69384d1391f52e007d533cb4319d3826cf3046ec1df27","src/ir/extfunc.rs":"69a838ddeb29fec19c6b308540259b971eb85be0fbab84647d68bd36d1f79c3d","src/ir/extname.rs":"839e3d694e5c109bb594fe31c7d9dfe4f156bbc2eb695f3412fd39c325374b91","src/ir/function.rs":"05808190e4764acdda07dd2f5750853310f06aa8848e3612dfce074f17837261","src/ir/globalvalue.rs":"8c9bc996332f6c7cb549a1d1296ed9f5783d364c1a5c9b5250745d412729f2be","src/ir/heap.rs":"dc9d4f0eade20d58b3e2678c329452fbd5965c46d6121cbf5889f2588ae88772","src/ir/immediates.rs":"0f1806af474a6bef2a4a488fae7b42482c6b05b4cf658069c6881b48b6b68ab0","src/ir/instructions.rs":"40a41505497fc03d2e0f25b3739378252a94566383b446016fa3be0879ddc1c8","src/ir/jumptable.rs":"7dae4bbc9538d05a6fc969800146327eb96b7d75aff976807edece5c6166537c","src/ir/layout.rs":"daf934675b0cfc227080538cfa2329b519f748dcc9e21539ba903670801b86a1","src/ir/libcall.rs":"c4405665b00fc199c520e6b5d637189736307e69793db6ada67242feecabc852","src/ir/memflags.rs":"988a07cf60facaee75c867b093332e311664ecfe405e2cf29ef5c59376f2ef61","src/ir/mod.rs":"2ac265cd091915aee161dd34c34f3b17d3590412bc41c09c763fa2d92a6bb626","src/ir/progpoint.rs":"d5191447f82bb612ae25ebceb5ecc2099a902be5aaecd5b9d418dcbd8a2747a5","src/ir/sourceloc.rs":"79eb71609b844839994fc735cd72edf53179eb659303a4150634928e207cee4f","src/ir/stackslot.rs":"669fb7b1692012d7c51fa53c3a1e49774045fc68d9c4a47995aeb7fb3e0027d4","src/ir/table.rs":"810e92631257e1e54577563df1da9709134438d0eab3db5e540500e69437a16b","src/ir/trapcode.rs":"233d73e4a2abbfc767aac7868d4adbb24cedaf8e7e42a640d590bda2e776784a","src/ir/types.rs":"50c3b48a60be236b37342063ee473ec4115d6d965a12673ac1588b050025f030","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":"da68e5ad27697b75ef34440cea045d077d8050026b6f279e40536c44be64a1b3","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":"be67ce9475a2b2fdeee12ff4eae76fe3d2a6919807f1d015b501e16135e82471","src/isa/arm64/registers.rs":"7a8b207ed28737efc737e8e65ce79e7e7d3eecd23599890230dca8474c985026","src/isa/arm64/settings.rs":"7b466fcc2c58bc1846a72f08ec58900b3cf622ab2922ee9128e6dfe254907bf5","src/isa/constraints.rs":"324d7c8655565f13b90a6c9587c9fb6c545ab3086201f434e1324fc5d6e5b3c7","src/isa/enc_tables.rs":"b6cf1a2e58a34170360681f517d89bb7aac1ed7586792e3d36156ca7326abcc5","src/isa/encoding.rs":"c8746f8c432a02e092dae80a9342734da760ad055854d598ffb395a47ed9d884","src/isa/mod.rs":"f86fad997fd136a3c44c70d3d7ca221a6bce64e8c1e69bea32fe1554bca9642b","src/isa/registers.rs":"9116fa8eb488b5d1e96f6718825cc4220a3f283ba629548a44267167c9683df8","src/isa/riscv/abi.rs":"1de6d0070126e0127ca6a63551a14d1b5c030cf9628538fd732301fd2bd34b5e","src/isa/riscv/binemit.rs":"3bdad2791447f51bfe5ecedb73b1aed8a6a8809790b1f26e3ff624a89163a026","src/isa/riscv/enc_tables.rs":"9c0303ef10098dc0a99021cddc3432e222874bff1d4b8f8ddc7daa05c6b77ddb","src/isa/riscv/mod.rs":"9a7a6ca8ba9273f772b3b7507072ec46975d067f572f71d86067bb8ed854b077","src/isa/riscv/registers.rs":"794ac61343a8db66dc99b2ca964ea3986b47b37fe8b72575c644c1cdaabd2991","src/isa/riscv/settings.rs":"78ced69b82d89f83b5612a91d0acdac2616f9091b380ee3e4715adb31f95b232","src/isa/stack.rs":"ec96130c446cd7d637722f1603e38d5164498368b652f4b0454baf3227385ad4","src/isa/x86/abi.rs":"bccfac45421a01002aae42acf8a14fdbc17e44299f08e10abaf0507578e744e3","src/isa/x86/binemit.rs":"48df284ed2cff76cea1e94cd08a6badd513787123ddf4984c495d745d6e59756","src/isa/x86/enc_tables.rs":"ac913a8fc45b1d5a863ce3dd760692e32ccb5f4f47fadd6b9f26f9df51b963d2","src/isa/x86/mod.rs":"146d059936b85ceb4983b3bcc9b875b7eaccbc5c1a9d34c435b8c4f7a737d87d","src/isa/x86/registers.rs":"783ebbe4c3b4711fe1eac2cfd3bbea7c31a53c15c6028397c038ef4eb0b2aa06","src/isa/x86/settings.rs":"dcce098045c1115cd55f256dcd3e0ccaa5a0c9ad93b14fb8a4c680e95caf2b73","src/iterators.rs":"f85f52d3fa707a0eb974c92215b3e976923ce8f9481219f7812e0f2869c2bd37","src/legalizer/boundary.rs":"d070da577a4a11a3bed9adbfdf94bec8aff368b4d176b1b85a44739545561a1c","src/legalizer/call.rs":"12f380d126765f0bc2da1cf298088fa98451e2d6bf56c34b755ff7077d14a4f1","src/legalizer/globalvalue.rs":"eb5d19a653928e2da0b78e38555b1d41f9549eeeca9fb6295a7dc5197ebd3c3f","src/legalizer/heap.rs":"c44a0845254187dfe7456b0b9efbfea25ae566772bc64b41ed93dd32a71f8e8a","src/legalizer/libcall.rs":"bf18267f502bf9bfbc3ff51bc05df480293a84422ea7f4c37dd0c75e97952766","src/legalizer/mod.rs":"c3707143cdd2b215b15ce7c0fa95d0df36a2cbf2e13dbe08d7166afa2e416f7a","src/legalizer/split.rs":"ae07854aad2ff2aa83a6ba08276b49a462dda0591faa9a61bdc7ca787451078f","src/legalizer/table.rs":"2aca27ea564c2ef02ed833c495156b9e1ddcee3c8a1b1e70347ab5907a381605","src/lib.rs":"95e48756b120856a91094e76c0acfc34abe86d93fe0bb9771063e7aec1af8315","src/licm.rs":"9657ccfdcf7a52eca1ba201d455f1d538f17aaa6295b9651282de9f7c79a53b9","src/loop_analysis.rs":"9b622be0af7a36f9ed2fb91bd4b6905785b63e0fc88d5765dd5f18a06f2f7834","src/nan_canonicalization.rs":"e2b1f9935d14af9abe553de1eda5483cffdaa7098dd1a17ba9a98fa04280b22c","src/partition_slice.rs":"55b9e857f452baf4d6312779861f9ef93b3d5300467e752230ec6af14943efe3","src/postopt.rs":"6a182d8646d6964c7137320bcd4b3c5cada62cac31a34e41050d3d6eeeaa9a98","src/predicates.rs":"fdb15850c86b9b45a13a1e791ef51ce843460b20e360d44dbdfdf198f59dc40d","src/preopt.rs":"cfafd0398bba0b3e2b91b5bf10617bd4048ba2b22345b3e5bfc403239903960a","src/print_errors.rs":"89b9f516c0567bada88e8fa9aea7d8e9f5acadbaea3ae5cb8215619433f1e5ee","src/ref_slice.rs":"9be914b705eefcc6b4e38db573f56ad7b978f4b65c2f6f8f5516df78fb2206a4","src/regalloc/affinity.rs":"47e28f9ae7cebfc9b1006480143a3a5ab1b118ec761a163c4a670b63fdc47d0a","src/regalloc/coalescing.rs":"253e3fb916c37453f0fa4f963caf5336712d60447e39f63a6696c2ad22cb102f","src/regalloc/coloring.rs":"fdcb1bda766220a7be0f815d8431e317dfc007a409c2c095948b45032a98c3e7","src/regalloc/context.rs":"794f9f0fb3b980feb3be57b95c152767cb318b81aca48c27197b01b7d529c48d","src/regalloc/diversion.rs":"cbb942a197081f9e537f3fed71a7ec6d6d1edc18b8536fa46a1dda316f46c776","src/regalloc/live_value_tracker.rs":"054efd9e8da0f33a158082f67a7c2c14f7c8632b1fc28d54941ca7bc9d5a46d6","src/regalloc/liveness.rs":"b21e4855c0339c1b15b1b62e63bb1a569c4256b42d08c3c21b6e7fc4634c5e62","src/regalloc/liverange.rs":"c7395c8c3709996f8d17a196af541ddbb37a9a20b1c3c151dd10628000ece337","src/regalloc/mod.rs":"6254df639f9289fd578e01b7dca99bc9c9e3c6680c6d031405e8df8d0cff31ad","src/regalloc/pressure.rs":"7c73ca1f54559b1d9f8ce587bdc067e74f3d47901058f7ae1e9277516624236f","src/regalloc/register_set.rs":"e1554d01a3a5a13acc4e0092681eb3fc090d9c68eb71f8a9985c01c7a3f2e3e2","src/regalloc/reload.rs":"cab64c91c57831d17e7e5ec217639f127b7608aedbfcb3c25cf3b9dfae36812d","src/regalloc/solver.rs":"853c6f16f68e75add56981b132d92e556a94d8cbd13fed311df2d75da08de03a","src/regalloc/spilling.rs":"eb7c625395c790ada187c0938dbcca6d43426a7f6d4a9ef0317778790a9dc38f","src/regalloc/virtregs.rs":"fb06b52b9b8ab0e139cb03105785ca94057c08c9277423317fb4c0040844ddde","src/result.rs":"d43abf9b22c5ad772200889bba339bcc4455c7abb9f2f3a2af65fbbaf1130009","src/scoped_hash_map.rs":"102797c380a588f7c16d26bf3b6c9cff28d37c2d8168a382b265194cd8969212","src/settings.rs":"2b0ddf77a4e18cf15292673502150b6b0af4d22ba03be9d1aadb654b6c1f91e1","src/simple_gvn.rs":"4d765fe40c527cbcac287a59d513dcc7b983d060893017579ec2b4f57b1411fc","src/stack_layout.rs":"ce0b4b188cc46fa5070139124ffb2d263d44acd08703e7043a40b5c1afa952fb","src/timing.rs":"d974dc0498ee814e90c5ecaaf60949f1b8d97213c4676114ed3d88affac56a02","src/topo_order.rs":"4ea901ec69bc1112ae496f26fea7de1f48cb2f1c1726525b367496fd3b4b3f23","src/unreachable_code.rs":"6fdea8f9afe9fbffe411bfef48fec7937cb41d51036fd190a3d0a5f0cc2894c6","src/verifier/cssa.rs":"8f41765d18474575faa7c44a0345549dabe0af07141e2f004a7db1c67486ce77","src/verifier/flags.rs":"80ecfdac53899ab4f35e8ba3f948b8cb32768184608bc0864029cf6d953d6c5c","src/verifier/liveness.rs":"6e827f05461bd6fb21b0ce99f02fae374f2d6ea6e7e14ba61e88983a1c6fac4b","src/verifier/locations.rs":"c3fbc688e021f5dabf20ea435cfa09da5e757229de6d9ef0465522898f44d0bd","src/verifier/mod.rs":"8fa2e17ef36a0a265b617a696edca33dc9fc5bcce5aace1519214f58d102bc60","src/write.rs":"f3bec214b6f6ef8f1ce11e056a5b14365d2adc122bbf725127b6ebb04c8dcc5b"},"package":"16f418f1d1e6221812a7d35cff5b9a572dc978c002e33792134bbd50c07cacca"}
\ 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.20.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.20.0"
 default-features = false
 
 [dependencies.cranelift-entity]
-version = "0.23.0"
+version = "0.20.0"
 default-features = false
 
 [dependencies.failure]
 version = "0.1.1"
 features = ["derive"]
 default-features = false
 
 [dependencies.failure_derive]
@@ -40,26 +40,26 @@ version = "0.1.1"
 default-features = false
 
 [dependencies.hashmap_core]
 version = "0.1.9"
 optional = true
 
 [dependencies.log]
 version = "0.4.4"
+features = ["release_max_level_warn"]
 default-features = false
 
 [dependencies.target-lexicon]
-version = "0.2.0"
+version = "0.0.3"
 default-features = false
 [build-dependencies.cranelift-codegen-meta]
-version = "0.23.0"
+version = "0.20.0"
 
 [features]
 core = ["hashmap_core"]
 default = ["std"]
 std = ["cranelift-entity/std", "cranelift-bforest/std", "target-lexicon/std"]
-testing_hooks = []
 [badges.maintenance]
 status = "experimental"
 
 [badges.travis-ci]
 repository = "CraneStation/cranelift"
--- a/third_party/rust/cranelift-codegen/LICENSE
+++ b/third_party/rust/cranelift-codegen/LICENSE
@@ -212,9 +212,8 @@ with the conditions of Sections 4(a), 4(
 In addition, if you combine or link compiled forms of this Software with
 software that is licensed under the GPLv2 ("Combined Software") and if a
 court of competent jurisdiction determines that the patent provision (Section
 3), the indemnity provision (Section 9) or other Section of the License
 conflicts with the conditions of the GPLv2, you may retroactively and
 prospectively choose to deem waived or otherwise exclude such Section(s) of
 the License, but only in their entirety and only with respect to the Combined
 Software.
-
--- a/third_party/rust/cranelift-codegen/build.rs
+++ b/third_party/rust/cranelift-codegen/build.rs
@@ -15,44 +15,41 @@
 //     A setting for conditional compilation of isa targets. Possible values can be "native" or
 //     known isa targets separated by ','.
 //
 // The build script expects to be run from the directory where this build.rs file lives. The
 // 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) {
         Ok(isa_targets) => {
             for isa in &isa_targets {
-                println!("cargo:rustc-cfg=build_{}", isa.to_string());
+                println!("cargo:rustc-cfg=build_{}", isa.name());
             }
         }
         Err(err) => {
             eprintln!("Error: {}", err);
             process::exit(1);
         }
     }
 
+    println!("Build script generating files in {}", out_dir);
+
     let cur_dir = env::current_dir().expect("Can't access current working directory");
     let crate_dir = cur_dir.as_path();
 
     // Make sure we rebuild if this build script changes.
     // I guess that won't happen if you have non-UTF8 bytes in your path names.
     // The `build.py` script prints out its own dependencies.
     println!(
         "cargo:rerun-if-changed={}",
@@ -78,53 +75,89 @@ fn main() {
         process::exit(status.code().unwrap());
     }
 
     // DEVELOPMENT:
     // ------------------------------------------------------------------------
     // Now that the Python build process is complete, generate files that are
     // emitted by the `meta` crate.
     // ------------------------------------------------------------------------
-    let isas = meta::isa::define_all();
-
-    if let Err(err) = meta::gen_types::generate("types.rs", &out_dir) {
+    if let Err(err) = meta::gen_types::generate("new_types.rs", &out_dir) {
         eprintln!("Error: {}", err);
         process::exit(1);
     }
-
-    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()
         {
             return python;
         }
     }
     panic!("The Cranelift build requires Python (version 2.7 or version 3)");
 }
 
+/// Represents known ISA target.
+#[derive(Copy, Clone)]
+enum Isa {
+    Riscv,
+    X86,
+    Arm32,
+    Arm64,
+}
+
+impl Isa {
+    /// Creates isa target using name.
+    fn new(name: &str) -> Option<Self> {
+        Isa::all()
+            .iter()
+            .cloned()
+            .filter(|isa| isa.name() == name)
+            .next()
+    }
+
+    /// Creates isa target from arch.
+    fn from_arch(arch: &str) -> Option<Isa> {
+        Isa::all()
+            .iter()
+            .cloned()
+            .filter(|isa| isa.is_arch_applicable(arch))
+            .next()
+    }
+
+    /// Returns all supported isa targets.
+    fn all() -> [Isa; 4] {
+        [Isa::Riscv, Isa::X86, Isa::Arm32, Isa::Arm64]
+    }
+
+    /// Returns name of the isa target.
+    fn name(&self) -> &'static str {
+        match *self {
+            Isa::Riscv => "riscv",
+            Isa::X86 => "x86",
+            Isa::Arm32 => "arm32",
+            Isa::Arm64 => "arm64",
+        }
+    }
+
+    /// Checks if arch is applicable for the isa target.
+    fn is_arch_applicable(&self, arch: &str) -> bool {
+        match *self {
+            Isa::Riscv => arch == "riscv",
+            Isa::X86 => ["x86_64", "i386", "i586", "i686"].contains(&arch),
+            Isa::Arm32 => arch.starts_with("arm") || arch.starts_with("thumb"),
+            Isa::Arm64 => arch == "aarch64",
+        }
+    }
+}
+
 /// Returns isa targets to configure conditional compilation.
 fn isa_targets(cranelift_targets: Option<&str>, target_triple: &str) -> Result<Vec<Isa>, String> {
     match cranelift_targets {
         Some("native") => Isa::from_arch(target_triple.split('-').next().unwrap())
             .map(|isa| vec![isa])
             .ok_or_else(|| {
                 format!(
                     "no supported isa found for target triple `{}`",
--- a/third_party/rust/cranelift-codegen/meta-python/base/formats.py
+++ b/third_party/rust/cranelift-codegen/meta-python/base/formats.py
@@ -45,20 +45,17 @@ FloatCond = InstructionFormat(floatcc, V
 
 IntSelect = InstructionFormat(intcc, VALUE, VALUE, VALUE)
 
 Jump = InstructionFormat(ebb, VARIABLE_ARGS)
 Branch = InstructionFormat(VALUE, ebb, VARIABLE_ARGS)
 BranchInt = InstructionFormat(intcc, VALUE, ebb, VARIABLE_ARGS)
 BranchFloat = InstructionFormat(floatcc, VALUE, ebb, VARIABLE_ARGS)
 BranchIcmp = InstructionFormat(intcc, VALUE, VALUE, ebb, VARIABLE_ARGS)
-BranchTable = InstructionFormat(VALUE, ebb, entities.jump_table)
-BranchTableEntry = InstructionFormat(VALUE, VALUE, uimm8, entities.jump_table)
-BranchTableBase = InstructionFormat(entities.jump_table)
-IndirectJump = InstructionFormat(VALUE, entities.jump_table)
+BranchTable = InstructionFormat(VALUE, entities.jump_table)
 
 Call = InstructionFormat(func_ref, VARIABLE_ARGS)
 CallIndirect = InstructionFormat(sig_ref, VALUE, VARIABLE_ARGS)
 FuncAddr = InstructionFormat(func_ref)
 
 Load = InstructionFormat(memflags, VALUE, offset32)
 LoadComplex = InstructionFormat(memflags, VARIABLE_ARGS, offset32)
 Store = InstructionFormat(memflags, VALUE, VALUE, offset32)
--- a/third_party/rust/cranelift-codegen/meta-python/base/instructions.py
+++ b/third_party/rust/cranelift-codegen/meta-python/base/instructions.py
@@ -125,66 +125,29 @@ f = Operand('f', fflags)
 
 brff = Instruction(
         'brff', r"""
         Branch when condition is true in floating point CPU flags.
         """,
         ins=(Cond, f, EBB, args), is_branch=True)
 
 x = Operand('x', iB, doc='index into jump table')
-Entry = TypeVar('Entry', 'A scalar integer type', ints=True)
-entry = Operand('entry', Entry, doc='entry of jump table')
 JT = Operand('JT', entities.jump_table)
 br_table = Instruction(
         'br_table', r"""
         Indirect branch via jump table.
 
         Use ``x`` as an unsigned index into the jump table ``JT``. If a jump
         table entry is found, branch to the corresponding EBB. If no entry was
-        found or the index is out-of-bounds, branch to the given default EBB.
+        found fall through to the next instruction.
 
         Note that this branch instruction can't pass arguments to the targeted
         blocks. Split critical edges as needed to work around this.
         """,
-        ins=(x, EBB, JT), is_branch=True, is_terminator=True)
-
-Size = Operand('Size', uimm8, 'Size in bytes')
-jump_table_entry = Instruction(
-    'jump_table_entry', r"""
-    Get an entry from a jump table.
-
-    Load a serialized ``entry`` from a jump table ``JT`` at a given index
-    ``addr`` with a specific ``Size``. The retrieved entry may need to be
-    decoded after loading, depending upon the jump table type used.
-
-    Currently, the only type supported is entries which are relative to the
-    base of the jump table.
-    """,
-    ins=(x, addr, Size, JT), outs=entry)
-
-jump_table_base = Instruction(
-    'jump_table_base', r"""
-    Get the absolute base address of a jump table.
-
-    This is used for jump tables wherein the entries are stored relative to
-    the base of jump table. In order to use these, generated code should first
-    load an entry using ``jump_table_entry``, then use this instruction to add
-    the relative base back to it.
-    """,
-    ins=JT, outs=addr)
-
-indirect_jump_table_br = Instruction(
-    'indirect_jump_table_br', r"""
-    Branch indirectly via a jump table entry.
-
-    Unconditionally jump via a jump table entry that was previously loaded
-    with the ``jump_table_entry`` instruction.
-    """,
-    ins=(addr, JT),
-    is_branch=True, is_indirect_branch=True, is_terminator=True)
+        ins=(x, JT), is_branch=True)
 
 code = Operand('code', trapcode)
 trap = Instruction(
         'trap', r"""
         Terminate execution unconditionally.
         """,
         ins=code, is_terminator=True, can_trap=True)
 
@@ -229,26 +192,16 @@ x_return = Instruction(
         Return from the function.
 
         Unconditionally transfer control to the calling function, passing the
         provided return values. The list of return values must match the
         function signature's return types.
         """,
         ins=rvals, is_return=True, is_terminator=True)
 
-fallthrough_return = Instruction(
-        'fallthrough_return', r"""
-        Return from the function by fallthrough.
-
-        This is a specialized instruction for use where one wants to append
-        a custom epilogue, which will then perform the real return. This
-        instruction has no encoding.
-        """,
-        ins=rvals, is_return=True, is_terminator=True)
-
 FN = Operand(
         'FN',
         entities.func_ref,
         doc='function to call, declared by :inst:`function`')
 args = Operand('args', VARIABLE_ARGS, doc='call arguments')
 
 call = Instruction(
         'call', r"""
@@ -544,25 +497,25 @@ stack_addr = Instruction(
 #
 
 GV = Operand('GV', entities.global_value)
 
 global_value = Instruction(
         'global_value', r"""
         Compute the value of global GV.
         """,
-        ins=GV, outs=a)
+        ins=GV, outs=addr)
 
 # A specialized form of global_value instructions that only handles
 # symbolic names.
-symbol_value = Instruction(
-        'symbol_value', r"""
-        Compute the value of global GV, which is a symbolic value.
+globalsym_addr = Instruction(
+        'globalsym_addr', r"""
+        Compute the address of global GV, which is a symbolic name.
         """,
-        ins=GV, outs=a)
+        ins=GV, outs=addr)
 
 #
 # WebAssembly bounds-checked heap accesses.
 #
 
 HeapOffset = TypeVar('HeapOffset', 'An unsigned heap offset', ints=(32, 64))
 
 H = Operand('H', entities.heap)
@@ -839,17 +792,17 @@ hi = Operand('hi', TxN.half_vector(), do
 vsplit = Instruction(
         'vsplit', r"""
         Split a vector into two halves.
 
         Split the vector `x` into two separate values, each containing half of
         the lanes from ``x``. The result may be two scalars if ``x`` only had
         two lanes.
         """,
-        ins=x, outs=(lo, hi), is_ghost=True)
+        ins=x, outs=(lo, hi))
 
 Any128 = TypeVar(
         'Any128', 'Any scalar or vector type with as most 128 lanes',
         ints=True, floats=True, bools=True, scalars=True, simd=(1, 128))
 x = Operand('x', Any128, doc='Low-numbered lanes')
 y = Operand('y', Any128, doc='High-numbered lanes')
 a = Operand('a', Any128.double_vector(), doc='Concatenation of `x` and `y`')
 
@@ -859,17 +812,17 @@ vconcat = Instruction(
 
         Return a vector formed by concatenating ``x`` and ``y``. The resulting
         vector type has twice as many lanes as each of the inputs. The lanes of
         ``x`` appear as the low-numbered lanes, and the lanes of ``y`` become
         the high-numbered lanes of ``a``.
 
         It is possible to form a vector by concatenating two scalars.
         """,
-        ins=(x, y), outs=a, is_ghost=True)
+        ins=(x, y), outs=a)
 
 c = Operand('c', TxN.as_bool(), doc='Controlling vector')
 x = Operand('x', TxN, doc='Value to use where `c` is true')
 y = Operand('y', TxN, doc='Value to use where `c` is false')
 a = Operand('a', TxN)
 
 vselect = Instruction(
         'vselect', r"""
@@ -1129,17 +1082,17 @@ srem_imm = Instruction(
         Signed integer remainder with immediate divisor.
 
         This operation traps if the divisor is zero.
         """,
         ins=(x, Y), outs=a)
 
 irsub_imm = Instruction(
         'irsub_imm', """
-        Immediate reverse wrapping subtraction: :math:`a := Y - x \\pmod{2^B}`.
+        Immediate reverse wrapping subtraction: :math:`a := Y - x \pmod{2^B}`.
 
         Also works as integer negation when :math:`Y = 0`. Use :inst:`iadd_imm`
         with a negative immediate operand for the reverse immediate
         subtraction.
 
         Polymorphic over all scalar integer types, but does not support vector
         types.
         """,
@@ -1451,24 +1404,16 @@ sshr_imm = Instruction(
 
 #
 # Bit counting.
 #
 
 x = Operand('x', iB)
 a = Operand('a', iB)
 
-bitrev = Instruction(
-        'bitrev', r"""
-        Reverse the bits of a integer.
-
-        Reverses the bits in ``x``.
-        """,
-        ins=x, outs=a)
-
 clz = Instruction(
         'clz', r"""
         Count leading zero bits.
 
         Starting from the MSB in ``x``, count the number of zero bits before
         reaching the first one bit. When ``x`` is zero, returns the size of x
         in bits.
         """,
@@ -2004,17 +1949,17 @@ isplit = Instruction(
         Split an integer into low and high parts.
 
         Vectors of integers are split lane-wise, so the results have the same
         number of lanes as the input, but the lanes are half the size.
 
         Returns the low half of `x` and the high half of `x` as two independent
         values.
         """,
-        ins=x, outs=(lo, hi), is_ghost=True)
+        ins=x, outs=(lo, hi))
 
 
 NarrowInt = TypeVar(
         'NarrowInt', 'An integer type with lanes type to `i32`',
         ints=(8, 32), simd=True)
 lo = Operand('lo', NarrowInt)
 hi = Operand('hi', NarrowInt)
 a = Operand(
@@ -2024,11 +1969,11 @@ a = Operand(
 iconcat = Instruction(
         'iconcat', r"""
         Concatenate low and high bits to form a larger integer type.
 
         Vectors of integers are concatenated lane-wise such that the result has
         the same number of lanes as the inputs, but the lanes are twice the
         size.
         """,
-        ins=(lo, hi), outs=a, is_ghost=True)
+        ins=(lo, hi), outs=a)
 
 GROUP.close()
--- a/third_party/rust/cranelift-codegen/meta-python/base/legalize.py
+++ b/third_party/rust/cranelift-codegen/meta-python/base/legalize.py
@@ -21,27 +21,19 @@ from .instructions import bnot, band_not
 from .instructions import band_imm, bor_imm, bxor_imm
 from .instructions import icmp, icmp_imm, ifcmp, ifcmp_imm
 from .instructions import iconst, bint, select
 from .instructions import ishl, ishl_imm, sshr, sshr_imm, ushr, ushr_imm
 from .instructions import rotl, rotl_imm, rotr, rotr_imm
 from .instructions import f32const, f64const
 from .instructions import store, load
 from .instructions import br_table
-from .instructions import bitrev
 from cdsl.ast import Var
 from cdsl.xform import Rtl, XFormGroup
 
-try:
-    from typing import TYPE_CHECKING # noqa
-    if TYPE_CHECKING:
-        from cdsl.instructions import Instruction # noqa
-except ImportError:
-    TYPE_CHECKING = False
-
 
 narrow = XFormGroup('narrow', """
         Legalize instructions by narrowing.
 
         The transformations in the 'narrow' group work by expressing
         instructions in terms of smaller types. Operations on vector types are
         expressed in terms of vector types with fewer lanes, and integer
         operations are expressed in terms of smaller integer types.
@@ -91,49 +83,30 @@ expand.custom_legalize(insts.f32const, '
 expand.custom_legalize(insts.f64const, 'expand_fconst')
 
 # Custom expansions for stack memory accesses.
 expand.custom_legalize(insts.stack_load, 'expand_stack_load')
 expand.custom_legalize(insts.stack_store, 'expand_stack_store')
 
 x = Var('x')
 y = Var('y')
-z = Var('z')
 a = Var('a')
 a1 = Var('a1')
 a2 = Var('a2')
-a3 = Var('a3')
-a4 = Var('a4')
 b = Var('b')
 b1 = Var('b1')
 b2 = Var('b2')
-b3 = Var('b3')
-b4 = Var('b4')
 b_in = Var('b_in')
 b_int = Var('b_int')
 c = Var('c')
 c1 = Var('c1')
 c2 = Var('c2')
-c3 = Var('c3')
-c4 = Var('c4')
 c_in = Var('c_in')
 c_int = Var('c_int')
 d = Var('d')
-d1 = Var('d1')
-d2 = Var('d2')
-d3 = Var('d3')
-d4 = Var('d4')
-e = Var('e')
-e1 = Var('e1')
-e2 = Var('e2')
-e3 = Var('e3')
-e4 = Var('e4')
-f = Var('f')
-f1 = Var('f1')
-f2 = Var('f2')
 xl = Var('xl')
 xh = Var('xh')
 yl = Var('yl')
 yh = Var('yh')
 al = Var('al')
 ah = Var('ah')
 cc = Var('cc')
 ptr = Var('ptr')
@@ -177,163 +150,25 @@ narrow.legalize(
         Rtl(
             (xl, xh) << isplit(x),
             (yl, yh) << isplit(y),
             al << select(c, xl, yl),
             ah << select(c, xh, yh),
             a << iconcat(al, ah)
         ))
 
-
-def widen_one_arg(signed, op):
-    # type: (bool, Instruction) -> None
-    for int_ty in [types.i8, types.i16]:
-        if signed:
-            widen.legalize(
-                a << op.bind(int_ty)(b),
-                Rtl(
-                    x << sextend.i32(b),
-                    z << op.i32(x),
-                    a << ireduce.bind(int_ty)(z)
-                ))
-        else:
-            widen.legalize(
-                a << op.bind(int_ty)(b),
-                Rtl(
-                    x << uextend.i32(b),
-                    z << op.i32(x),
-                    a << ireduce.bind(int_ty)(z)
-                ))
-
-
-def widen_two_arg(signed, op):
-    # type: (bool, Instruction) -> None
-    for int_ty in [types.i8, types.i16]:
-        if signed:
-            widen.legalize(
-                a << op.bind(int_ty)(b, c),
-                Rtl(
-                    x << sextend.i32(b),
-                    y << sextend.i32(c),
-                    z << op.i32(x, y),
-                    a << ireduce.bind(int_ty)(z)
-                ))
-        else:
-            widen.legalize(
-                a << op.bind(int_ty)(b, c),
-                Rtl(
-                    x << uextend.i32(b),
-                    y << uextend.i32(c),
-                    z << op.i32(x, y),
-                    a << ireduce.bind(int_ty)(z)
-                ))
-
-
-def widen_imm(signed, op):
-    # type: (bool, Instruction) -> None
-    for int_ty in [types.i8, types.i16]:
-        if signed:
-            widen.legalize(
-                a << op.bind(int_ty)(b, c),
-                Rtl(
-                    x << sextend.i32(b),
-                    z << op.i32(x, c),
-                    a << ireduce.bind(int_ty)(z)
-                ))
-        else:
-            widen.legalize(
-                a << op.bind(int_ty)(b, c),
-                Rtl(
-                    x << uextend.i32(b),
-                    z << op.i32(x, c),
-                    a << ireduce.bind(int_ty)(z)
-                ))
-
-
-# int ops
-for binop in [iadd, isub, imul, udiv, urem]:
-    widen_two_arg(False, binop)
-
-for binop in [sdiv, srem]:
-    widen_two_arg(True, binop)
-
-for binop in [iadd_imm, imul_imm, udiv_imm, urem_imm]:
-    widen_imm(False, binop)
-
-for binop in [sdiv_imm, srem_imm]:
-    widen_imm(True, binop)
-
-widen_imm(False, irsub_imm)
-
-# bit ops
-widen_one_arg(False, bnot)
-
-for binop in [band, bor, bxor, band_not, bor_not, bxor_not]:
-    widen_two_arg(False, binop)
-
-for binop in [band_imm, bor_imm, bxor_imm]:
-    widen_imm(False, binop)
-
-widen_one_arg(False, insts.popcnt)
-
-for (int_ty, num) in [(types.i8, 24), (types.i16, 16)]:
-    widen.legalize(
-        a << insts.clz.bind(int_ty)(b),
-        Rtl(
-            c << uextend.i32(b),
-            d << insts.clz.i32(c),
-            e << iadd_imm(d, imm64(-num)),
-            a << ireduce.bind(int_ty)(e)
-        ))
-
-    widen.legalize(
-        a << insts.cls.bind(int_ty)(b),
-        Rtl(
-            c << sextend.i32(b),
-            d << insts.cls.i32(c),
-            e << iadd_imm(d, imm64(-num)),
-            a << ireduce.bind(int_ty)(e)
-        ))
-
-for (int_ty, num) in [(types.i8, 1 << 8), (types.i16, 1 << 16)]:
-    widen.legalize(
-        a << insts.ctz.bind(int_ty)(b),
-        Rtl(
-            c << uextend.i32(b),
-            # When `b` is zero, returns the size of x in bits.
-            d << bor_imm(c, imm64(num)),
-            e << insts.ctz.i32(d),
-            a << ireduce.bind(int_ty)(e)
-        ))
-
-# iconst
 for int_ty in [types.i8, types.i16]:
     widen.legalize(
         a << iconst.bind(int_ty)(b),
         Rtl(
             c << iconst.i32(b),
             a << ireduce.bind(int_ty)(c)
         ))
 
 widen.legalize(
-    a << uextend.i16.i8(b),
-    Rtl(
-        c << uextend.i32(b),
-        a << ireduce(c)
-    ))
-
-widen.legalize(
-    a << sextend.i16.i8(b),
-    Rtl(
-        c << sextend.i32(b),
-        a << ireduce(c)
-    ))
-
-
-widen.legalize(
     store.i8(flags, a, ptr, offset),
     Rtl(
         b << uextend.i32(a),
         insts.istore8(flags, b, ptr, offset)
     ))
 
 widen.legalize(
     store.i16(flags, a, ptr, offset),
@@ -351,100 +186,91 @@ widen.legalize(
 
 widen.legalize(
     a << load.i16(flags, ptr, offset),
     Rtl(
         b << insts.uload16.i32(flags, ptr, offset),
         a << ireduce(b)
     ))
 
+for binop in [iadd, isub, imul, udiv, band, bor, bxor]:
+    for int_ty in [types.i8, types.i16]:
+        widen.legalize(
+            a << binop.bind(int_ty)(x, y),
+            Rtl(
+                b << uextend.i32(x),
+                c << uextend.i32(y),
+                d << binop(b, c),
+                a << ireduce(d)
+            )
+        )
+
+for binop in [sdiv]:
+    for int_ty in [types.i8, types.i16]:
+        widen.legalize(
+            a << binop.bind(int_ty)(x, y),
+            Rtl(
+                b << sextend.i32(x),
+                c << sextend.i32(y),
+                d << binop(b, c),
+                a << ireduce(d)
+            )
+        )
+
+for unop in [bnot]:
+    for int_ty in [types.i8, types.i16]:
+        widen.legalize(
+            a << unop.bind(int_ty)(x),
+            Rtl(
+                b << sextend.i32(x),
+                d << unop(b),
+                a << ireduce(d)
+            )
+        )
+
+for binop in [iadd_imm, imul_imm, udiv_imm]:
+    for int_ty in [types.i8, types.i16]:
+        widen.legalize(
+            a << binop.bind(int_ty)(x, y),
+            Rtl(
+                b << uextend.i32(x),
+                c << binop(b, y),
+                a << ireduce(c)
+            )
+        )
+
+for binop in [sdiv_imm]:
+    for int_ty in [types.i8, types.i16]:
+        widen.legalize(
+            a << binop.bind(int_ty)(x, y),
+            Rtl(
+                b << sextend.i32(x),
+                c << binop(b, y),
+                a << ireduce(c)
+            )
+        )
+
 for int_ty in [types.i8, types.i16]:
     widen.legalize(
-        br_table.bind(int_ty)(x, y, z),
+        br_table.bind(int_ty)(x, y),
         Rtl(
             b << uextend.i32(x),
-            br_table(b, y, z),
+            br_table(b, y),
         )
     )
 
 for int_ty in [types.i8, types.i16]:
     widen.legalize(
         a << insts.bint.bind(int_ty)(b),
         Rtl(
             x << insts.bint.i32(b),
             a << ireduce.bind(int_ty)(x)
         )
     )
 
-for int_ty in [types.i8, types.i16]:
-    for op in [ushr_imm, ishl_imm]:
-        widen.legalize(
-            a << op.bind(int_ty)(b, c),
-            Rtl(
-                x << uextend.i32(b),
-                z << op.i32(x, c),
-                a << ireduce.bind(int_ty)(z)
-            ))
-
-    widen.legalize(
-        a << ishl.bind(int_ty)(b, c),
-        Rtl(
-            x << uextend.i32(b),
-            z << ishl.i32(x, c),
-            a << ireduce.bind(int_ty)(z)
-        ))
-
-    widen.legalize(
-        a << ushr.bind(int_ty)(b, c),
-        Rtl(
-            x << uextend.i32(b),
-            z << ushr.i32(x, c),
-            a << ireduce.bind(int_ty)(z)
-        ))
-
-    widen.legalize(
-        a << sshr.bind(int_ty)(b, c),
-        Rtl(
-            x << sextend.i32(b),
-            z << sshr.i32(x, c),
-            a << ireduce.bind(int_ty)(z)
-        ))
-
-    for w_cc in [
-        intcc.eq, intcc.ne, intcc.ugt, intcc.ult, intcc.uge, intcc.ule
-    ]:
-        widen.legalize(
-            a << insts.icmp_imm.bind(int_ty)(w_cc, b, c),
-            Rtl(
-                x << uextend.i32(b),
-                a << insts.icmp_imm(w_cc, x, c)
-            ))
-        widen.legalize(
-            a << insts.icmp.bind(int_ty)(w_cc, b, c),
-            Rtl(
-                x << uextend.i32(b),
-                y << uextend.i32(c),
-                a << insts.icmp.i32(w_cc, x, y)
-            ))
-    for w_cc in [intcc.sgt, intcc.slt, intcc.sge, intcc.sle]:
-        widen.legalize(
-            a << insts.icmp_imm.bind(int_ty)(w_cc, b, c),
-            Rtl(
-                x << sextend.i32(b),
-                a << insts.icmp_imm(w_cc, x, c)
-            ))
-        widen.legalize(
-            a << insts.icmp.bind(int_ty)(w_cc, b, c),
-            Rtl(
-                x << sextend.i32(b),
-                y << sextend.i32(c),
-                a << insts.icmp(w_cc, x, y)
-            )
-        )
-
 # Expand integer operations with carry for RISC architectures that don't have
 # the flags.
 expand.legalize(
         (a, c) << iadd_cout(x, y),
         Rtl(
             a << iadd(x, y),
             c << icmp(intcc.ult, a, x)
         ))
@@ -551,125 +377,16 @@ for inst_not,      inst in [
 # Expand bnot using xor.
 expand.legalize(
         a << bnot(x),
         Rtl(
             y << iconst(imm64(-1)),
             a << bxor(x, y)
         ))
 
-# Expand bitrev
-# Adapted from Stack Overflow.
-# https://stackoverflow.com/questions/746171/most-efficient-algorithm-for-bit-reversal-from-msb-lsb-to-lsb-msb-in-c
-widen.legalize(
-        a << bitrev.i8(x),
-        Rtl(
-            a1 << band_imm(x, imm64(0xaa)),
-            a2 << ushr_imm(a1, imm64(1)),
-            a3 << band_imm(x, imm64(0x55)),
-            a4 << ishl_imm(a3, imm64(1)),
-            b << bor(a2, a4),
-            b1 << band_imm(b, imm64(0xcc)),
-            b2 << ushr_imm(b1, imm64(2)),
-            b3 << band_imm(b, imm64(0x33)),
-            b4 << ushr_imm(b3, imm64(2)),
-            c << bor(b2, b4),
-            c1 << band_imm(c, imm64(0xf0)),
-            c2 << ushr_imm(c1, imm64(4)),
-            c3 << band_imm(c, imm64(0x0f)),
-            c4 << ishl_imm(c3, imm64(4)),
-            a << bor(c2, c4),
-        ))
-
-widen.legalize(
-        a << bitrev.i16(x),
-        Rtl(
-            a1 << band_imm(x, imm64(0xaaaa)),
-            a2 << ushr_imm(a1, imm64(1)),
-            a3 << band_imm(x, imm64(0x5555)),
-            a4 << ishl_imm(a3, imm64(1)),
-            b << bor(a2, a4),
-            b1 << band_imm(b, imm64(0xcccc)),
-            b2 << ushr_imm(b1, imm64(2)),
-            b3 << band_imm(b, imm64(0x3333)),
-            b4 << ushr_imm(b3, imm64(2)),
-            c << bor(b2, b4),
-            c1 << band_imm(c, imm64(0xf0f0)),
-            c2 << ushr_imm(c1, imm64(4)),
-            c3 << band_imm(c, imm64(0x0f0f)),
-            c4 << ishl_imm(c3, imm64(4)),
-            d << bor(c2, c4),
-            d1 << band_imm(d, imm64(0xff00)),
-            d2 << ushr_imm(d1, imm64(8)),
-            d3 << band_imm(d, imm64(0x00ff)),
-            d4 << ishl_imm(d3, imm64(8)),
-            a << bor(d2, d4),
-        ))
-
-expand.legalize(
-        a << bitrev.i32(x),
-        Rtl(
-            a1 << band_imm(x, imm64(0xaaaaaaaa)),
-            a2 << ushr_imm(a1, imm64(1)),
-            a3 << band_imm(x, imm64(0x55555555)),
-            a4 << ishl_imm(a3, imm64(1)),
-            b << bor(a2, a4),
-            b1 << band_imm(b, imm64(0xcccccccc)),
-            b2 << ushr_imm(b1, imm64(2)),
-            b3 << band_imm(b, imm64(0x33333333)),
-            b4 << ushr_imm(b3, imm64(2)),
-            c << bor(b2, b4),
-            c1 << band_imm(c, imm64(0xf0f0f0f0)),
-            c2 << ushr_imm(c1, imm64(4)),
-            c3 << band_imm(c, imm64(0x0f0f0f0f)),
-            c4 << ishl_imm(c3, imm64(4)),
-            d << bor(c2, c4),
-            d1 << band_imm(d, imm64(0xff00ff00)),
-            d2 << ushr_imm(d1, imm64(8)),
-            d3 << band_imm(d, imm64(0x00ff00ff)),
-            d4 << ishl_imm(d3, imm64(8)),
-            e << bor(d2, d4),
-            e1 << ushr_imm(e, imm64(16)),
-            e2 << ishl_imm(e, imm64(16)),
-            a << bor(e1, e2),
-        ))
-
-expand.legalize(
-        a << bitrev.i64(x),
-        Rtl(
-            a1 << band_imm(x, imm64(0xaaaaaaaaaaaaaaaa)),
-            a2 << ushr_imm(a1, imm64(1)),
-            a3 << band_imm(x, imm64(0x5555555555555555)),
-            a4 << ishl_imm(a3, imm64(1)),
-            b << bor(a2, a4),
-            b1 << band_imm(b, imm64(0xcccccccccccccccc)),
-            b2 << ushr_imm(b1, imm64(2)),
-            b3 << band_imm(b, imm64(0x3333333333333333)),
-            b4 << ushr_imm(b3, imm64(2)),
-            c << bor(b2, b4),
-            c1 << band_imm(c, imm64(0xf0f0f0f0f0f0f0f0)),
-            c2 << ushr_imm(c1, imm64(4)),
-            c3 << band_imm(c, imm64(0x0f0f0f0f0f0f0f0f)),
-            c4 << ishl_imm(c3, imm64(4)),
-            d << bor(c2, c4),
-            d1 << band_imm(d, imm64(0xff00ff00ff00ff00)),
-            d2 << ushr_imm(d1, imm64(8)),
-            d3 << band_imm(d, imm64(0x00ff00ff00ff00ff)),
-            d4 << ishl_imm(d3, imm64(8)),
-            e << bor(d2, d4),
-            e1 << band_imm(e, imm64(0xffff0000ffff0000)),
-            e2 << ushr_imm(e1, imm64(16)),
-            e3 << band_imm(e, imm64(0x0000ffff0000ffff)),
-            e4 << ishl_imm(e3, imm64(16)),
-            f << bor(e2, e4),
-            f1 << ushr_imm(f, imm64(32)),
-            f2 << ishl_imm(f, imm64(32)),
-            a << bor(f1, f2),
-        ))
-
 # Floating-point sign manipulations.
 for ty,             minus_zero in [
         (types.f32, f32const(ieee32.bits(0x80000000))),
         (types.f64, f64const(ieee64.bits(0x8000000000000000)))]:
     expand.legalize(
             a << insts.fabs.bind(ty)(x),
             Rtl(
                 b << minus_zero,
--- a/third_party/rust/cranelift-codegen/meta-python/base/settings.py
+++ b/third_party/rust/cranelift-codegen/meta-python/base/settings.py
@@ -22,30 +22,64 @@ enable_verifier = BoolSetting(
         """
         Run the Cranelift IR verifier at strategic times during compilation.
 
         This makes compilation slower but catches many bugs. The verifier is
         disabled by default, except when reading Cranelift IR from a text file.
         """,
         default=True)
 
+call_conv = EnumSetting(
+        """
+        Default calling convention:
+
+        - fast: not-ABI-stable convention for best performance
+        - cold: not-ABI-stable convention for infrequently executed code
+        - system_v: System V-style convention used on many platforms
+        - windows_fastcall: Windows "fastcall" convention, also used for
+                            x64 and ARM
+        - baldrdash: SpiderMonkey WebAssembly convention
+        - probestack: specialized convention for the probestack function
+
+        The default calling convention may be overridden by individual
+        functions.
+        """,
+
+        'fast',
+        'cold',
+        'system_v',
+        'windows_fastcall',
+        'baldrdash',
+        'probestack'
+)
+
 # Note that Cranelift doesn't currently need an is_pie flag, because PIE is
 # just PIC where symbols can't be pre-empted, which can be expressed with the
 # `colocated` flag on external functions and global values.
 is_pic = BoolSetting("Enable Position-Independent Code generation")
 
 colocated_libcalls = BoolSetting(
         """
         Use colocated libcalls.
 
         Generate code that assumes that libcalls can be declared "colocated",
         meaning they will be defined along with the current function, such that
         they can use more efficient addressing.
         """)
 
+return_at_end = BoolSetting(
+        """
+        Generate functions with at most a single return instruction at the
+        end of the function.
+
+        This guarantees that functions do not have any internal return
+        instructions. Either they never return, or they have a single return
+        instruction at the end.
+        """)
+
 avoid_div_traps = BoolSetting(
         """
         Generate explicit checks around native division instructions to avoid
         their trapping.
 
         This is primarily used by SpiderMonkey which doesn't install a signal
         handler for SIGFPE, but expects a SIGILL trap for division by zero.
 
@@ -127,18 +161,9 @@ probestack_size_log2 = NumSetting(
 
         Stack frames larger than this size will have stack overflow checked
         by calling the probestack function.
 
         The default is 12, which translates to a size of 4096.
         """,
         default=12)
 
-#
-# Jump table options.
-#
-jump_tables_enabled = BoolSetting(
-        """
-        Enable the use of jump tables in generated machine code.
-        """,
-        default=True)
-
 group.close(globals())
--- a/third_party/rust/cranelift-codegen/meta-python/base/types.py
+++ b/third_party/rust/cranelift-codegen/meta-python/base/types.py
@@ -1,24 +1,21 @@
 """
 The base.types module predefines all the Cranelift scalar types.
 """
 from __future__ import absolute_import
 from cdsl.types import IntType, FloatType, BoolType, FlagsType
 
-#: Abstract boolean (can't be stored in memory, use bint to convert to 0 or 1).
-b1 = BoolType(1)    #: 1-bit bool.
-
-#: Booleans used as SIMD elements (can be stored in memory, true is all-ones).
+#: Boolean.
+b1 = BoolType(1)    #: 1-bit bool. Type is abstract (can't be stored in mem)
 b8 = BoolType(8)    #: 8-bit bool.
 b16 = BoolType(16)  #: 16-bit bool.
 b32 = BoolType(32)  #: 32-bit bool.
 b64 = BoolType(64)  #: 64-bit bool.
 
-# Integers.
 i8 = IntType(8)     #: 8-bit int.
 i16 = IntType(16)   #: 16-bit int.
 i32 = IntType(32)   #: 32-bit int.
 i64 = IntType(64)   #: 64-bit int.
 
 #: IEEE single precision.
 f32 = FloatType(
         32, """
--- a/third_party/rust/cranelift-codegen/meta-python/build.py
+++ b/third_party/rust/cranelift-codegen/meta-python/build.py
@@ -1,36 +1,40 @@
 # Second-level build script.
 #
 # This script is run from lib/codegen/build.rs to generate Rust files.
 
 from __future__ import absolute_import
 import argparse
 import isa
+import gen_types
 import gen_instr
 import gen_settings
 import gen_build_deps
 import gen_encoding
 import gen_legalizer
+import gen_registers
 import gen_binemit
 
 
 def main():
     # type: () -> None
     parser = argparse.ArgumentParser(
             description='Generate sources for Cranelift.')
     parser.add_argument('--out-dir', help='set output directory')
 
     args = parser.parse_args()
     out_dir = args.out_dir
 
     isas = isa.all_isas()
 
+    gen_types.generate(out_dir)
     gen_instr.generate(isas, out_dir)
     gen_settings.generate(isas, out_dir)
     gen_encoding.generate(isas, out_dir)
     gen_legalizer.generate(isas, out_dir)
+    gen_registers.generate(isas, out_dir)
     gen_binemit.generate(isas, out_dir)
     gen_build_deps.generate()
 
 
 if __name__ == "__main__":
     main()
--- a/third_party/rust/cranelift-codegen/meta-python/cdsl/ast.py
+++ b/third_party/rust/cranelift-codegen/meta-python/cdsl/ast.py
@@ -518,24 +518,20 @@ class ConstantInt(Literal):
     """
 
     def __init__(self, kind, value):
         # type: (ImmediateKind, int) -> None
         super(ConstantInt, self).__init__(kind, value)
 
     def __str__(self):
         # type: () -> str
-        # If the value is in the signed imm64 range, print it as-is.
-        if self.value >= -(2**63) and self.value < (2**63):
-            return str(self.value)
-        # Otherwise if the value is in the unsigned imm64 range, print its
-        # bitwise counterpart in the signed imm64 range.
-        if self.value >= (2**63) and self.value < (2**64):
-            return str(self.value - (2**64))
-        assert False, "immediate value not in signed or unsigned imm64 range"
+        """
+        Get the Rust expression form of this constant.
+        """
+        return str(self.value)
 
 
 class ConstantBits(Literal):
     """
     A bitwise value of an immediate operand.
 
     This is used to create bitwise exact floating point constants using
     `ieee32.bits(0x80000000)`.
--- a/third_party/rust/cranelift-codegen/meta-python/cdsl/instructions.py
+++ b/third_party/rust/cranelift-codegen/meta-python/cdsl/instructions.py
@@ -84,38 +84,32 @@ class Instruction(object):
     :param doc: Documentation string.
     :param ins: Tuple of input operands. This can be a mix of SSA value
                 operands and other operand kinds.
     :param outs: Tuple of output operands. The output operands must be SSA
                 values or `variable_args`.
     :param constraints: Tuple of instruction-specific TypeConstraints.
     :param is_terminator: This is a terminator instruction.
     :param is_branch: This is a branch instruction.
-    :param is_indirect_branch: This is an indirect branch instruction.
     :param is_call: This is a call instruction.
     :param is_return: This is a return instruction.
-    :param is_ghost: This is a ghost instruction, which has no encoding and no
-                     other register allocation constraints.
     :param can_trap: This instruction can trap.
     :param can_load: This instruction can load from memory.
     :param can_store: This instruction can store to memory.
     :param other_side_effects: Instruction has other side effects.
     """
 
     # Boolean instruction attributes that can be passed as keyword arguments to
     # the constructor. Map attribute name to doc comment for generated Rust
     # code.
     ATTRIBS = {
             'is_terminator': 'True for instructions that terminate the EBB.',
             'is_branch': 'True for all branch or jump instructions.',
-            'is_indirect_branch':
-            'True for all indirect branch or jump instructions.',
             'is_call': 'Is this a call instruction?',
             'is_return': 'Is this a return instruction?',
-            'is_ghost': 'Is this a ghost instruction?',
             'can_load': 'Can this instruction read from memory?',
             'can_store': 'Can this instruction write to memory?',
             'can_trap': 'Can this instruction cause a trap?',
             'other_side_effects':
             'Does this instruction have other side effects besides can_*',
             'writes_cpu_flags': 'Does this instruction write to CPU flags?',
             }
 
@@ -343,17 +337,17 @@ class Instruction(object):
 
     def fully_bound(self):
         # type: () -> Tuple[Instruction, Tuple[ValueType, ...]]
         """
         Verify that all typevars have been bound, and return a
         `(inst, typevars)` pair.
 
         This version in `Instruction` itself allows non-polymorphic
-        instructions to duck-type as `BoundInstruction`\\s.
+        instructions to duck-type as `BoundInstruction`\s.
         """
         assert not self.is_polymorphic, self
         return (self, ())
 
     def __call__(self, *args):
         # type: (*Expr) -> Apply
         """
         Create an `ast.Apply` AST node representing the application of this
--- a/third_party/rust/cranelift-codegen/meta-python/cdsl/isa.py
+++ b/third_party/rust/cranelift-codegen/meta-python/cdsl/isa.py
@@ -311,48 +311,44 @@ class EncRecipe(object):
 
     For ISAs that use CPU flags in `iflags` and `fflags` value types, the
     `clobbers_flags` is used to indicate instruction encodings that clobbers
     the CPU flags, so they can't be used where a flag value is live.
 
     :param name: Short mnemonic name for this recipe.
     :param format: All encoded instructions must have this
             :py:class:`InstructionFormat`.
-    :param base_size: Base number of bytes in the binary encoded instruction.
-    :param compute_size: Function name to use when computing actual size.
+    :param size: Number of bytes in the binary encoded instruction.
     :param ins: Tuple of register constraints for value operands.
     :param outs: Tuple of register constraints for results.
     :param branch_range: `(origin, bits)` range for branches.
     :param clobbers_flags: This instruction clobbers `iflags` and `fflags`.
     :param instp: Instruction predicate.
     :param isap: ISA predicate.
     :param emit: Rust code for binary emission.
     """
 
     def __init__(
             self,
-            name,                     # type: str
-            format,                   # type: InstructionFormat
-            base_size,                # type: int
-            ins,                      # type: ConstraintSeq
-            outs,                     # type: ConstraintSeq
-            compute_size=None,        # type: str
-            branch_range=None,        # type: BranchRange
-            clobbers_flags=True,      # type: bool
-            instp=None,               # type: PredNode
-            isap=None,                # type: PredNode
-            emit=None                 # type: str
+            name,                 # type: str
+            format,               # type: InstructionFormat
+            size,                 # type: int
+            ins,                  # type: ConstraintSeq
+            outs,                 # type: ConstraintSeq
+            branch_range=None,    # type: BranchRange
+            clobbers_flags=True,  # type: bool
+            instp=None,           # type: PredNode
+            isap=None,            # type: PredNode
+            emit=None             # type: str
             ):
         # type: (...) -> None
         self.name = name
         self.format = format
-        assert base_size >= 0
-        self.base_size = base_size
-        self.compute_size = compute_size if compute_size is not None \
-            else 'base_size'
+        assert size >= 0
+        self.size = size
         self.branch_range = branch_range
         self.clobbers_flags = clobbers_flags
         self.instp = instp
         self.isap = isap
         self.emit = emit
         if instp:
             assert instp.predicate_context() == format
         self.number = None  # type: int
@@ -468,17 +464,17 @@ class Encoding(object):
                     typred = TypePredicate.typevar_check(self.inst, tv, vt)
                     instp = And.combine(instp, typred)
 
         self.cpumode = cpumode
         assert self.inst.format == recipe.format, (
                 "Format {} must match recipe: {}".format(
                     self.inst.format, recipe.format))
 
-        if self.inst.is_branch and not self.inst.is_indirect_branch:
+        if self.inst.is_branch:
             assert recipe.branch_range, (
                     'Recipe {} for {} must have a branch_range'
                     .format(recipe, self.inst.name))
 
         self.recipe = recipe
         self.encbits = encbits
 
         # Record specific predicates. Note that the recipe also has predicates.
--- a/third_party/rust/cranelift-codegen/meta-python/cdsl/predicates.py
+++ b/third_party/rust/cranelift-codegen/meta-python/cdsl/predicates.py
@@ -239,17 +239,17 @@ class FieldPredicate(object):
 
     def rust_predicate(self, prec):
         # type: (int) -> str
         """
         Return a string of Rust code that evaluates this predicate.
         """
         # Prepend `field` to the predicate function arguments.
         args = (self.field.rust_name(),) + tuple(map(str, self.args))
-        return '::predicates::{}({})'.format(self.function, ', '.join(args))
+        return 'predicates::{}({})'.format(self.function, ', '.join(args))
 
 
 class IsEqual(FieldPredicate):
     """
     Instruction predicate that checks if an immediate instruction format field
     is equal to a constant value.
 
     :param field: `FormatField` to be checked.
--- a/third_party/rust/cranelift-codegen/meta-python/cdsl/registers.py
+++ b/third_party/rust/cranelift-codegen/meta-python/cdsl/registers.py
@@ -82,16 +82,17 @@ class RegBank(object):
         self.isa = isa
         self.first_unit = 0
         self.units = units
         self.pressure_tracking = pressure_tracking
         self.prefix = prefix
         self.names = names
         self.classes = list()  # type: List[RegClass]
         self.toprcs = list()  # type: List[RegClass]
+        self.first_toprc_index = None  # type: int
 
         assert len(names) <= units
 
         if isa.regbanks:
             # Get the next free unit number.
             last = isa.regbanks[-1]
             u = last.first_unit + last.units
             align = units
@@ -242,17 +243,17 @@ class RegClass(object):
         The tuple can be used as a dictionary key to ensure that there are no
         duplicate register classes.
         """
         return (self.width, self.bitmask)
 
     def intersect(self, other):
         # type: (RegClass) -> RCTup
         """
-        Get a tuple representing the intersection of two register classes.
+        Get a tuple representing the intersction of two register classes.
 
         Returns `None` if the two classes are disjoint.
         """
         if self.width != other.width:
             return None
         intersection = self.bitmask & other.bitmask
         if intersection == 0:
             return None
--- a/third_party/rust/cranelift-codegen/meta-python/cdsl/test_ti.py
+++ b/third_party/rust/cranelift-codegen/meta-python/cdsl/test_ti.py
@@ -93,17 +93,17 @@ def check_typing(got_or_err, expected, s
 
 
 def check_concrete_typing_rtl(var_types, rtl):
     # type: (VarTyping, Rtl) -> None
     """
     Check that a concrete type assignment var_types (Dict[Var, TypeVar]) is
     valid for an Rtl rtl. Specifically check that:
 
-    1) For each Var v \\in rtl, v is defined in var_types
+    1) For each Var v \in rtl, v is defined in var_types
 
     2) For all v, var_types[v] is a singleton type
 
     3) For each v, and each location u, where v is used with expected type
        tv_u, var_types[v].get_typeset() is a subset of
        subst(tv_u, m).get_typeset() where m is the substitution of
        formals->actuals we are building so far.
 
--- a/third_party/rust/cranelift-codegen/meta-python/cdsl/ti.py
+++ b/third_party/rust/cranelift-codegen/meta-python/cdsl/ti.py
@@ -21,24 +21,16 @@ except ImportError:
     TYPE_CHECKING = False
     pass
 
 
 class TypeConstraint(object):
     """
     Base class for all runtime-emittable type constraints.
     """
-
-    def __init__(self, tv, tc):
-        # type: (TypeVar, Union[TypeVar, TypeSet]) -> None
-        """
-        Abstract "constructor" for linters
-        """
-        assert False, "Abstract"
-
     def translate(self, m):
         # type: (Union[TypeEnv, TypeMap]) -> TypeConstraint
         """
         Translate any TypeVars in the constraint according to the map or
         TypeEnv m
         """
         def translate_one(a):
             # type: (Any) -> Any
@@ -78,17 +70,17 @@ class TypeConstraint(object):
         """
         assert False, "Abstract"
 
     def tvs(self):
         # type: () -> Iterable[TypeVar]
         """
         Return the typevars contained in this constraint.
         """
-        return list(filter(lambda x: isinstance(x, TypeVar), self._args()))
+        return filter(lambda x:  isinstance(x, TypeVar), self._args())
 
     def is_trivial(self):
         # type: () -> bool
         """
         Return true if this constrain is statically decidable.
         """
         assert False, "Abstract"
 
@@ -422,28 +414,28 @@ class TypeEnv(object):
         """
         Normalize by:
             - collapsing any roots that don't correspond to a concrete TV AND
               have a single TV derived from them or equivalent to them
 
         E.g. if we have a root of the tree that looks like:
 
           typeof_a   typeof_b
-                 \\  /
+                 \  /
               typeof_x
                   |
                 half_width(1)
                   |
                   1
 
         we want to collapse the linear path between 1 and typeof_x. The
         resulting graph is:
 
           typeof_a   typeof_b
-                 \\  /
+                 \  /
               typeof_x
         """
         source_tvs = set([v.get_typevar() for v in self.vars])
         children = {}  # type: Dict[TypeVar, Set[TypeVar]]
         for v in self.type_map.values():
             if not v.is_derived:
                 continue
 
--- a/third_party/rust/cranelift-codegen/meta-python/cdsl/types.py
+++ b/third_party/rust/cranelift-codegen/meta-python/cdsl/types.py
@@ -174,17 +174,17 @@ class SpecialType(ValueType):
     A concrete scalar type that is neither a vector nor a lane type.
 
     Special types cannot be used to form vectors.
     """
 
     def __init__(self, name, membytes, doc):
         # type: (str, int, str) -> None
         super(SpecialType, self).__init__(name, membytes, doc)
-        # Assign numbers starting from 1. (0 is INVALID)
+        # Assign numbers starting from 1. (0 is VOID)
         ValueType.all_special_types.append(self)
         self.number = len(ValueType.all_special_types)
         assert self.number < LANE_BASE, 'Too many special types'
 
     def __repr__(self):
         # type: () -> str
         return 'SpecialType({})'.format(self.name)
 
--- a/third_party/rust/cranelift-codegen/meta-python/cdsl/typevar.py
+++ b/third_party/rust/cranelift-codegen/meta-python/cdsl/typevar.py
@@ -115,17 +115,17 @@ def interval_to_set(intv):
     assert lo <= hi
     return set([2**i for i in range(int_log2(lo), int_log2(hi)+1)])
 
 
 def legal_bool(bits):
     # type: (int) -> bool
     """
     True iff bits is a legal bit width for a bool type.
-    bits == 1 || bits \\in { 8, 16, .. MAX_BITS }
+    bits == 1 || bits \in { 8, 16, .. MAX_BITS }
     """
     return bits == 1 or \
         (bits >= 8 and bits <= MAX_BITS and is_power_of_two(bits))
 
 
 class TypeSet(object):
     """
     A set of types.
--- a/third_party/rust/cranelift-codegen/meta-python/cdsl/xform.py
+++ b/third_party/rust/cranelift-codegen/meta-python/cdsl/xform.py
@@ -108,17 +108,17 @@ class Rtl(object):
         """Return True iff every Var in the self has a singleton type."""
         return all(v.get_typevar().singleton_type() is not None
                    for v in self.vars())
 
     def cleanup_concrete_rtl(self):
         # type: (Rtl) -> None
         """
         Given that there is only 1 possible concrete typing T for self, assign
-        a singleton TV with type t=T[v] for each Var v \\in self. Its an error
+        a singleton TV with type t=T[v] for each Var v \in self. Its an error
         to call this on an Rtl with more than 1 possible typing. This modifies
         the Rtl in-place.
         """
         from .ti import ti_rtl, TypeEnv
         # 1) Infer the types of all vars in res
         typenv = get_type_env(ti_rtl(self, TypeEnv()))
         typenv.normalize()
         typenv = typenv.extract()
--- a/third_party/rust/cranelift-codegen/meta-python/gen_encoding.py
+++ b/third_party/rust/cranelift-codegen/meta-python/gen_encoding.py
@@ -17,18 +17,18 @@ This is the information available to us:
   This is needed for testing any secondary type variables.
 - A `PredicateView` reference for the ISA-specific settings for evaluating ISA
   predicates.
 - The currently active CPU mode is determined by the ISA.
 
 ## Level 1 table lookup
 
 The CPU mode provides the first table. The key is the instruction's controlling
-type variable. If the instruction is not polymorphic, use `INVALID` for the
-type variable. The table values are level 2 tables.
+type variable. If the instruction is not polymorphic, use `VOID` for the type
+variable. The table values are level 2 tables.
 
 ## Level 2 table lookup
 
 The level 2 table is keyed by the instruction's opcode. The table values are
 *encoding lists*.
 
 The two-level table lookup allows the level 2 tables to be much smaller with
 good locality. Code in any given function usually only uses a few different
@@ -677,25 +677,25 @@ def emit_level1_hashtable(cpumode, level
 
     with fmt.indented(
             'pub static LEVEL1_{}: [Level1Entry<{}>; {}] = ['
             .format(cpumode.name.upper(), offt, len(hash_table)), '];'):
         for level2 in hash_table:
             # Empty hash table entry. Include the default legalization action.
             if not level2:
                 fmt.format(
-                        'Level1Entry {{ ty: ir::types::INVALID, log2len: !0, '
+                        'Level1Entry {{ ty: ir::types::VOID, log2len: !0, '
                         'offset: 0, legalize: {} }},',
                         level1.legalize_code)
                 continue
 
             if level2.ty is not None:
                 tyname = level2.ty.rust_name()
             else:
-                tyname = 'ir::types::INVALID'
+                tyname = 'ir::types::VOID'
 
             lcode = cpumode.isa.legalize_code(level2.legalize)
 
             # Empty level 2 table: Only a specialized legalization action, no
             # actual table.
             # Set an offset that is out of bounds, but make sure it doesn't
             # overflow its type when adding `1<<log2len`.
             if level2.is_empty():
@@ -827,18 +827,17 @@ def emit_recipe_sizing(isa, fmt):
     Emit a table of encoding recipe code size information.
     """
     with fmt.indented(
             'static RECIPE_SIZING: [RecipeSizing; {}] = ['
             .format(len(isa.all_recipes)), '];'):
         for r in isa.all_recipes:
             fmt.comment('Code size information for recipe {}:'.format(r.name))
             with fmt.indented('RecipeSizing {', '},'):
-                fmt.format('base_size: {},', r.base_size)
-                fmt.format('compute_size: {},', r.compute_size)
+                fmt.format('bytes: {},', r.size)
                 if r.branch_range:
                     fmt.format(
                         'branch_range: '
                         'Some(BranchRange {{ origin: {}, bits: {} }}),',
                         *r.branch_range)
                 else:
                     fmt.line('branch_range: None,')
 
--- a/third_party/rust/cranelift-codegen/meta-python/gen_instr.py
+++ b/third_party/rust/cranelift-codegen/meta-python/gen_instr.py
@@ -102,20 +102,21 @@ def gen_arguments_method(fmt, is_mut):
         fmt.match(m)
 
 
 def gen_instruction_data(fmt):
     # type: (srcgen.Formatter) -> None
     """
     Generate the InstructionData enum.
 
-    Every variant must contain an `opcode` field. The size of `InstructionData`
-    should be kept at 16 bytes on 64-bit architectures. If more space is needed
-    to represent an instruction, use a `Box<AuxData>` to store the additional
-    information out of line.
+    Every variant must contain `opcode` and `ty` fields. An instruction that
+    doesn't produce a value should have its `ty` field set to `VOID`. The size
+    of `InstructionData` should be kept at 16 bytes on 64-bit architectures. If
+    more space is needed to represent an instruction, use a `Box<AuxData>` to
+    store the additional information out of line.
     """
 
     fmt.line('#[derive(Clone, Debug)]')
     fmt.line('#[allow(missing_docs)]')
     with fmt.indented('pub enum InstructionData {', '}'):
         for f in InstructionFormat.all_formats:
             with fmt.indented('{} {{'.format(f.name), '},'):
                 fmt.line('opcode: Opcode,')
@@ -700,17 +701,17 @@ def gen_inst_builder(inst, fmt):
         # Arguments for instruction constructor.
         args = ['Opcode::' + inst.camel_name]
 
         if inst.is_polymorphic and not inst.use_typevar_operand:
             # This was an explicit method argument.
             args.append(inst.ctrl_typevar.name)
         elif not inst.is_polymorphic:
             # No controlling type variable needed.
-            args.append('types::INVALID')
+            args.append('types::VOID')
         else:
             assert inst.is_polymorphic and inst.use_typevar_operand
             # Infer the controlling type variable from the input operands.
             opnum = inst.value_opnums[inst.format.typevar_operand]
             fmt.line(
                     'let ctrl_typevar = self.data_flow_graph().value_type({});'
                     .format(inst.ins[opnum].name))
             # The format constructor will resolve the result types from the
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cranelift-codegen/meta-python/gen_registers.py
@@ -0,0 +1,109 @@
+"""
+Generate register bank descriptions for each ISA.
+"""
+
+from __future__ import absolute_import
+import srcgen
+
+try:
+    from typing import Sequence, List  # noqa
+    from cdsl.isa import TargetISA  # noqa
+    from cdsl.registers import RegBank, RegClass  # noqa
+except ImportError:
+    pass
+
+
+def gen_regbank(regbank, fmt):
+    # type: (RegBank, srcgen.Formatter) -> None
+    """
+    Emit a static data definition for regbank.
+    """
+    with fmt.indented('RegBank {', '},'):
+        fmt.format('name: "{}",', regbank.name)
+        fmt.format('first_unit: {},', regbank.first_unit)
+        fmt.format('units: {},', regbank.units)
+        fmt.format(
+                'names: &[{}],',
+                ', '.join('"{}"'.format(n) for n in regbank.names))
+        fmt.format('prefix: "{}",', regbank.prefix)
+        fmt.format('first_toprc: {},', regbank.toprcs[0].index)
+        fmt.format('num_toprcs: {},', len(regbank.toprcs))
+        fmt.format(
+                'pressure_tracking: {},',
+                'true' if regbank.pressure_tracking else 'false')
+
+
+def gen_regbank_units(regbank, fmt):
+    # type: (RegBank, srcgen.Formatter) -> None
+    """
+    Emit constants for all the register units in `regbank`.
+    """
+    for unit in range(regbank.units):
+        v = unit + regbank.first_unit
+        if unit < len(regbank.names):
+            fmt.format("{} = {},", regbank.names[unit], v)
+        else:
+            fmt.format("{}{} = {},", regbank.prefix, unit, v)
+
+
+def gen_regclass(rc, fmt):
+    # type: (RegClass, srcgen.Formatter) -> None
+    """
+    Emit a static data definition for a register class.
+    """
+    with fmt.indented(
+            'pub static {}_DATA: RegClassData = RegClassData {{'
+            .format(rc.name), '};'):
+        fmt.format('name: "{}",', rc.name)
+        fmt.format('index: {},', rc.index)
+        fmt.format('width: {},', rc.width)
+        fmt.format('bank: {},', rc.bank.index)
+        fmt.format('toprc: {},', rc.toprc.index)
+        fmt.format('first: {},', rc.bank.first_unit + rc.start())
+        fmt.format('subclasses: 0x{:x},', rc.subclass_mask())
+        mask = ', '.join('0x{:08x}'.format(x) for x in rc.mask())
+        fmt.format('mask: [{}],', mask)
+        fmt.line('info: &INFO,')
+    # Also emit a convenient reference for use by hand-written code.
+    fmt.line('#[allow(dead_code)]')
+    fmt.format('pub static {0}: RegClass = &{0}_DATA;', rc.name)
+
+
+def gen_isa(isa, fmt):
+    # type: (TargetISA, srcgen.Formatter) -> None
+    """
+    Generate register tables for isa.
+    """
+    if not isa.regbanks:
+        print('cargo:warning={} has no register banks'.format(isa.name))
+
+    with fmt.indented('pub static INFO: RegInfo = RegInfo {', '};'):
+        # Bank descriptors.
+        with fmt.indented('banks: &[', '],'):
+            for regbank in isa.regbanks:
+                gen_regbank(regbank, fmt)
+        with fmt.indented('classes: &[', '],'):
+            for rc in isa.regclasses:
+                fmt.format('&{}_DATA,', rc.name)
+
+    # Register class descriptors.
+    for rc in isa.regclasses:
+        gen_regclass(rc, fmt)
+
+    # Emit constants for all the register units.
+    fmt.line('#[allow(dead_code, non_camel_case_types)]')
+    fmt.line('#[derive(Clone, Copy)]')
+    with fmt.indented('pub enum RU {', '}'):
+        for regbank in isa.regbanks:
+            gen_regbank_units(regbank, fmt)
+    with fmt.indented('impl Into<RegUnit> for RU {', '}'):
+        with fmt.indented('fn into(self) -> RegUnit {', '}'):
+            fmt.line('self as RegUnit')
+
+
+def generate(isas, out_dir):
+    # type: (Sequence[TargetISA], str) -> None
+    for isa in isas:
+        fmt = srcgen.Formatter()
+        gen_isa(isa, fmt)
+        fmt.update_file('registers-{}.rs'.format(isa.name), out_dir)
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cranelift-codegen/meta-python/gen_types.py
@@ -0,0 +1,64 @@
+"""
+Generate sources with type info.
+
+This generates a `types.rs` file which is included in
+`lib/codegen/ir/types.rs`. The file provides constant definitions for the most
+commonly used types, including all of the scalar types.
+
+This ensures that Python and Rust use the same type numbering.
+"""
+from __future__ import absolute_import
+import srcgen
+from cdsl.types import ValueType
+import base.types  # noqa
+
+try:
+    from typing import Iterable  # noqa
+except ImportError:
+    pass
+
+
+def emit_type(ty, fmt):
+    # type: (ValueType, srcgen.Formatter) -> None
+    """
+    Emit a constant definition of a single value type.
+    """
+    name = ty.name.upper()
+    fmt.doc_comment(ty.__doc__)
+    fmt.line(
+            'pub const {}: Type = Type({:#x});'
+            .format(name, ty.number))
+    fmt.line()
+
+
+def emit_vectors(bits, fmt):
+    # type: (int, srcgen.Formatter) -> None
+    """
+    Emit definition for all vector types with `bits` total size.
+    """
+    size = bits // 8
+    for ty in ValueType.all_lane_types:
+        mb = ty.membytes
+        if mb == 0 or mb >= size:
+            continue
+        emit_type(ty.by(size // mb), fmt)
+
+
+def emit_types(fmt):
+    # type: (srcgen.Formatter) -> None
+    for spec in ValueType.all_special_types:
+        emit_type(spec, fmt)
+    for ty in ValueType.all_lane_types:
+        emit_type(ty, fmt)
+    # Emit vector definitions for common SIMD sizes.
+    emit_vectors(64, fmt)
+    emit_vectors(128, fmt)
+    emit_vectors(256, fmt)
+    emit_vectors(512, fmt)
+
+
+def generate(out_dir):
+    # type: (str) -> None
+    fmt = srcgen.Formatter()
+    emit_types(fmt)
+    fmt.update_file('types.rs', out_dir)
--- a/third_party/rust/cranelift-codegen/meta-python/isa/riscv/recipes.py
+++ b/third_party/rust/cranelift-codegen/meta-python/isa/riscv/recipes.py
@@ -88,138 +88,138 @@ def AIUPC():
 def LUI():
     # type: () -> int
     return 0b01101
 
 
 # R-type 32-bit instructions: These are mostly binary arithmetic instructions.
 # The encbits are `opcode[6:2] | (funct3 << 5) | (funct7 << 8)
 R = EncRecipe(
-        'R', Binary, base_size=4, ins=(GPR, GPR), outs=GPR,
+        'R', Binary, size=4, ins=(GPR, GPR), outs=GPR,
         emit='put_r(bits, in_reg0, in_reg1, out_reg0, sink);')
 
 # R-type with an immediate shift amount instead of rs2.
 Rshamt = EncRecipe(
-        'Rshamt', BinaryImm, base_size=4, ins=GPR, outs=GPR,
+        'Rshamt', BinaryImm, size=4, ins=GPR, outs=GPR,
         emit='put_rshamt(bits, in_reg0, imm.into(), out_reg0, sink);')
 
 # R-type encoding of an integer comparison.
 Ricmp = EncRecipe(
-        'Ricmp', IntCompare, base_size=4, ins=(GPR, GPR), outs=GPR,
+        'Ricmp', IntCompare, size=4, ins=(GPR, GPR), outs=GPR,
         emit='put_r(bits, in_reg0, in_reg1, out_reg0, sink);')
 
 Ii = EncRecipe(
-        'Ii', BinaryImm, base_size=4, ins=GPR, outs=GPR,
+        'Ii', BinaryImm, size=4, ins=GPR, outs=GPR,
         instp=IsSignedInt(BinaryImm.imm, 12),
         emit='put_i(bits, in_reg0, imm.into(), out_reg0, sink);')
 
 # I-type instruction with a hardcoded %x0 rs1.
 Iz = EncRecipe(
-        'Iz', UnaryImm, base_size=4, ins=(), outs=GPR,
+        'Iz', UnaryImm, size=4, ins=(), outs=GPR,
         instp=IsSignedInt(UnaryImm.imm, 12),
         emit='put_i(bits, 0, imm.into(), out_reg0, sink);')
 
 # I-type encoding of an integer comparison.
 Iicmp = EncRecipe(
-        'Iicmp', IntCompareImm, base_size=4, ins=GPR, outs=GPR,
+        'Iicmp', IntCompareImm, size=4, ins=GPR, outs=GPR,
         instp=IsSignedInt(IntCompareImm.imm, 12),
         emit='put_i(bits, in_reg0, imm.into(), out_reg0, sink);')
 
 # I-type encoding for `jalr` as a return instruction. We won't use the
 # immediate offset.
 # The variable return values are not encoded.
 Iret = EncRecipe(
-        'Iret', MultiAry, base_size=4, ins=(), outs=(),
+        'Iret', MultiAry, size=4, ins=(), outs=(),
         emit='''
         // Return instructions are always a jalr to %x1.
         // The return address is provided as a special-purpose link argument.
         put_i(
             bits,
             1, // rs1 = %x1
             0, // no offset.
             0, // rd = %x0: no address written.
             sink,
         );
         ''')
 
 # I-type encoding for `jalr` as a call_indirect.
 Icall = EncRecipe(
-        'Icall', CallIndirect, base_size=4, ins=GPR, outs=(),
+        'Icall', CallIndirect, size=4, ins=GPR, outs=(),
         emit='''
         // call_indirect instructions are jalr with rd=%x1.
         put_i(
             bits,
             in_reg0,
             0, // no offset.
             1, // rd = %x1: link register.
             sink,
         );
         ''')
 
 
 # Copy of a GPR is implemented as addi x, 0.
 Icopy = EncRecipe(
-        'Icopy', Unary, base_size=4, ins=GPR, outs=GPR,
+        'Icopy', Unary, size=4, ins=GPR, outs=GPR,
         emit='put_i(bits, in_reg0, 0, out_reg0, sink);')
 
 # Same for a GPR regmove.
 Irmov = EncRecipe(
-        'Irmov', RegMove, base_size=4, ins=GPR, outs=(),
+        'Irmov', RegMove, size=4, ins=GPR, outs=(),
         emit='put_i(bits, src, 0, dst, sink);')
 
 # U-type instructions have a 20-bit immediate that targets bits 12-31.
 U = EncRecipe(
-        'U', UnaryImm, base_size=4, ins=(), outs=GPR,
+        'U', UnaryImm, size=4, ins=(), outs=GPR,
         instp=IsSignedInt(UnaryImm.imm, 32, 12),
         emit='put_u(bits, imm.into(), out_reg0, sink);')
 
 # UJ-type unconditional branch instructions.
 UJ = EncRecipe(
-        'UJ', Jump, base_size=4, ins=(), outs=(), branch_range=(0, 21),
+        'UJ', Jump, size=4, ins=(), outs=(), branch_range=(0, 21),
         emit='''
         let dest = i64::from(func.offsets[destination]);
         let disp = dest - i64::from(sink.offset());
         put_uj(bits, disp, 0, sink);
         ''')
 
 UJcall = EncRecipe(
-        'UJcall', Call, base_size=4, ins=(), outs=(),
+        'UJcall', Call, size=4, ins=(), outs=(),
         emit='''
         sink.reloc_external(Reloc::RiscvCall,
                             &func.dfg.ext_funcs[func_ref].name,
                             0);
         // rd=%x1 is the standard link register.
         put_uj(bits, 0, 1, sink);
         ''')
 
 # SB-type branch instructions.
 SB = EncRecipe(
-        'SB', BranchIcmp, base_size=4,
+        'SB', BranchIcmp, size=4,
         ins=(GPR, GPR), outs=(),
         branch_range=(0, 13),
         emit='''
         let dest = i64::from(func.offsets[destination]);
         let disp = dest - i64::from(sink.offset());
         put_sb(bits, disp, in_reg0, in_reg1, sink);
         ''')
 
 # SB-type branch instruction with rs2 fixed to zero.
 SBzero = EncRecipe(
-        'SBzero', Branch, base_size=4,
+        'SBzero', Branch, size=4,
         ins=(GPR), outs=(),
         branch_range=(0, 13),
         emit='''
         let dest = i64::from(func.offsets[destination]);
         let disp = dest - i64::from(sink.offset());
         put_sb(bits, disp, in_reg0, 0, sink);
         ''')
 
 # Spill of a GPR.
 GPsp = EncRecipe(
-        'GPsp', Unary, base_size=4,
+        'GPsp', Unary, size=4,
         ins=GPR, outs=Stack(GPR),
         emit='unimplemented!();')
 
 # Fill of a GPR.
 GPfi = EncRecipe(
-        'GPfi', Unary, base_size=4,
+        'GPfi', Unary, size=4,
         ins=Stack(GPR), outs=GPR,
         emit='unimplemented!();')
--- a/third_party/rust/cranelift-codegen/meta-python/isa/x86/encodings.py
+++ b/third_party/rust/cranelift-codegen/meta-python/isa/x86/encodings.py
@@ -168,18 +168,17 @@ enc_both(base.bxor.b1, r.rr, 0x31)
 enc_i32_i64(base.imul, r.rrx, 0x0f, 0xaf)
 enc_i32_i64(x86.sdivmodx, r.div, 0xf7, rrr=7)
 enc_i32_i64(x86.udivmodx, r.div, 0xf7, rrr=6)
 
 enc_i32_i64(x86.smulx, r.mulx, 0xf7, rrr=5)
 enc_i32_i64(x86.umulx, r.mulx, 0xf7, rrr=4)
 
 enc_i32_i64(base.copy, r.umr, 0x89)
-for ty in [types.b1, types.i8, types.i16]:
-    enc_both(base.copy.bind(ty), r.umr, 0x89)
+enc_both(base.copy.b1, r.umr, 0x89)
 
 # For x86-64, only define REX forms for now, since we can't describe the
 # special regunit immediate operands with the current constraint language.
 for ty in [types.i8, types.i16, types.i32]:
     X86_32.enc(base.regmove.bind(ty), *r.rmov(0x89))
     X86_64.enc(base.regmove.bind(ty), *r.rmov.rex(0x89))
 X86_64.enc(base.regmove.i64, *r.rmov.rex(0x89, w=1))
 
@@ -297,39 +296,37 @@ for recipe in [r.st, r.stDisp8, r.stDisp
 # the corresponding st* recipes when a REX prefix is applied.
 for recipe in [r.st_abcd, r.stDisp8_abcd, r.stDisp32_abcd]:
     enc_both(base.istore8.i32.any, recipe, 0x88)
     enc_x86_64(base.istore8.i64.any, recipe, 0x88)
 
 enc_i32_i64(base.spill, r.spillSib32, 0x89)
 enc_i32_i64(base.regspill, r.regspill32, 0x89)
 
-# Use a 32-bit write for spilling `b1`, `i8` and `i16` to avoid
-# constraining the permitted registers.
+# Use a 32-bit write for spilling `b1` to avoid constraining the permitted
+# registers.
 # See MIN_SPILL_SLOT_SIZE which makes this safe.
-for ty in [types.b1, types.i8, types.i16]:
-    enc_both(base.spill.bind(ty), r.spillSib32, 0x89)
-    enc_both(base.regspill.bind(ty), r.regspill32, 0x89)
+enc_both(base.spill.b1, r.spillSib32, 0x89)
+enc_both(base.regspill.b1, r.regspill32, 0x89)
 
 for recipe in [r.ld, r.ldDisp8, r.ldDisp32]:
     enc_i32_i64_ld_st(base.load, True, recipe, 0x8b)
     enc_x86_64(base.uload32.i64, recipe, 0x8b)
     X86_64.enc(base.sload32.i64, *recipe.rex(0x63, w=1))
     enc_i32_i64_ld_st(base.uload16, True, recipe, 0x0f, 0xb7)
     enc_i32_i64_ld_st(base.sload16, True, recipe, 0x0f, 0xbf)
     enc_i32_i64_ld_st(base.uload8, True, recipe, 0x0f, 0xb6)
     enc_i32_i64_ld_st(base.sload8, True, recipe, 0x0f, 0xbe)
 
 enc_i32_i64(base.fill, r.fillSib32, 0x8b)
 enc_i32_i64(base.regfill, r.regfill32, 0x8b)
 
-# Load 32 bits from `b1`, `i8` and `i16` spill slots. See `spill.b1` above.
-for ty in [types.b1, types.i8, types.i16]:
-    enc_both(base.fill.bind(ty), r.fillSib32, 0x8b)
-    enc_both(base.regfill.bind(ty), r.regfill32, 0x8b)
+# Load 32 bits from `b1` spill slots. See `spill.b1` above.
+enc_both(base.fill.b1, r.fillSib32, 0x8b)
+enc_both(base.regfill.b1, r.regfill32, 0x8b)
 
 # Push and Pop
 X86_32.enc(x86.push.i32, *r.pushq(0x50))
 enc_x86_64(x86.push.i64, r.pushq, 0x50)
 
 X86_32.enc(x86.pop.i32, *r.popq(0x58))
 enc_x86_64(x86.pop.i64, r.popq, 0x58)
 
@@ -426,28 +423,28 @@ X86_64.enc(base.func_addr.i64, *r.pcrel_
 X86_64.enc(base.func_addr.i64, *r.got_fnaddr8.rex(0x8b, w=1),
            isap=is_pic)
 
 #
 # Global addresses.
 #
 
 # Non-PIC
-X86_32.enc(base.symbol_value.i32, *r.gvaddr4(0xb8),
+X86_32.enc(base.globalsym_addr.i32, *r.gvaddr4(0xb8),
            isap=Not(is_pic))
-X86_64.enc(base.symbol_value.i64, *r.gvaddr8.rex(0xb8, w=1),
+X86_64.enc(base.globalsym_addr.i64, *r.gvaddr8.rex(0xb8, w=1),
            isap=Not(is_pic))
 
 # PIC, colocated
-X86_64.enc(base.symbol_value.i64, *r.pcrel_gvaddr8.rex(0x8d, w=1),
+X86_64.enc(base.globalsym_addr.i64, *r.pcrel_gvaddr8.rex(0x8d, w=1),
            isap=is_pic,
            instp=IsColocatedData())
 
 # PIC, non-colocated
-X86_64.enc(base.symbol_value.i64, *r.got_gvaddr8.rex(0x8b, w=1),
+X86_64.enc(base.globalsym_addr.i64, *r.got_gvaddr8.rex(0x8b, w=1),
            isap=is_pic)
 
 #
 # Stack addresses.
 #
 # TODO: Add encoding rules for stack_load and stack_store, so that they
 # don't get legalized to stack_addr + load/store.
 #
@@ -506,27 +503,16 @@ X86_32.enc(base.brz.b1, *r.t8jccd_long(0
 X86_32.enc(base.brnz.b1, *r.t8jccd_long(0x85))
 
 enc_both(base.brz.b1, r.t8jccb_abcd, 0x74)
 enc_both(base.brz.b1, r.t8jccd_abcd, 0x84)
 enc_both(base.brnz.b1, r.t8jccb_abcd, 0x75)
 enc_both(base.brnz.b1, r.t8jccd_abcd, 0x85)
 
 #
-# Jump tables
-#
-X86_64.enc(base.jump_table_entry.i64.any.any, *r.jt_entry.rex(0x63, w=1))
-X86_32.enc(base.jump_table_entry.i32.any.any, *r.jt_entry(0x8b))
-
-X86_64.enc(base.jump_table_base.i64, *r.jt_base.rex(0x8d, w=1))
-X86_32.enc(base.jump_table_base.i32, *r.jt_base(0x8d))
-
-enc_x86_64(base.indirect_jump_table_br.i64, r.indirect_jmp, 0xff, rrr=4)
-X86_32.enc(base.indirect_jump_table_br.i32, *r.indirect_jmp(0xff, rrr=4))
-#
 # Trap as ud2
 #
 X86_32.enc(base.trap, *r.trap(0x0f, 0x0b))
 X86_64.enc(base.trap, *r.trap(0x0f, 0x0b))
 
 # Using a standard EncRecipe, not the TailRecipe.
 X86_32.enc(base.trapif, r.trapif, 0)
 X86_64.enc(base.trapif, r.trapif, 0)
@@ -576,21 +562,18 @@ X86_32.enc(base.bint.i32.b1, *r.urm_nofl
 X86_64.enc(base.bint.i64.b1, *r.urm_noflags.rex(0x0f, 0xb6))
 X86_64.enc(base.bint.i64.b1, *r.urm_noflags_abcd(0x0f, 0xb6))
 X86_64.enc(base.bint.i32.b1, *r.urm_noflags.rex(0x0f, 0xb6))
 X86_64.enc(base.bint.i32.b1, *r.urm_noflags_abcd(0x0f, 0xb6))
 
 # Numerical conversions.
 
 # Reducing an integer is a no-op.
-X86_32.enc(base.ireduce.i8.i16, r.null, 0)
 X86_32.enc(base.ireduce.i8.i32, r.null, 0)
 X86_32.enc(base.ireduce.i16.i32, r.null, 0)
-
-X86_64.enc(base.ireduce.i8.i16, r.null, 0)
 X86_64.enc(base.ireduce.i8.i32, r.null, 0)
 X86_64.enc(base.ireduce.i16.i32, r.null, 0)
 X86_64.enc(base.ireduce.i8.i64, r.null, 0)
 X86_64.enc(base.ireduce.i16.i64, r.null, 0)
 X86_64.enc(base.ireduce.i32.i64, r.null, 0)
 
 # TODO: Add encodings for cbw, cwde, cdqe, which are sign-extending
 # instructions for %al/%ax/%eax to %ax/%eax/%rax.
--- a/third_party/rust/cranelift-codegen/meta-python/isa/x86/recipes.py
+++ b/third_party/rust/cranelift-codegen/meta-python/isa/x86/recipes.py
@@ -9,23 +9,22 @@ from cdsl.registers import RegClass
 from base.formats import Unary, UnaryIeee32, UnaryIeee64, UnaryImm, UnaryBool
 from base.formats import Binary, BinaryImm
 from base.formats import MultiAry, NullAry
 from base.formats import Trap, Call, CallIndirect, Store, Load
 from base.formats import IntCompare, IntCompareImm, FloatCompare
 from base.formats import IntCond, FloatCond
 from base.formats import IntSelect, IntCondTrap, FloatCondTrap
 from base.formats import Jump, Branch, BranchInt, BranchFloat
-from base.formats import BranchTableEntry, BranchTableBase, IndirectJump
 from base.formats import Ternary, FuncAddr, UnaryGlobalValue
 from base.formats import RegMove, RegSpill, RegFill, CopySpecial
 from base.formats import LoadComplex, StoreComplex
 from base.formats import StackLoad
-from .registers import GPR, ABCD, FPR
-from .registers import GPR8, FPR8, FLAG
+from .registers import GPR, ABCD, FPR, GPR_DEREF_SAFE, GPR_ZERO_DEREF_SAFE
+from .registers import GPR8, FPR8, GPR8_DEREF_SAFE, GPR8_ZERO_DEREF_SAFE, FLAG
 from .registers import StackGPR32, StackFPR32
 from .defs import supported_floatccs
 from .settings import use_sse41
 
 try:
     from typing import Tuple, Dict, Sequence, Any  # noqa
     from cdsl.instructions import InstructionFormat  # noqa
     from cdsl.isa import ConstraintSeq, BranchRange, PredNode, OperandConstraint  # noqa
@@ -108,16 +107,18 @@ def replace_put_op(emit, prefix):
         return None
     else:
         return emit.replace('PUT_OP', 'put_' + prefix.lower())
 
 
 # Register class mapping for no-REX instructions.
 NOREX_MAP = {
         GPR: GPR8,
+        GPR_DEREF_SAFE: GPR8_DEREF_SAFE,
+        GPR_ZERO_DEREF_SAFE: GPR8_ZERO_DEREF_SAFE,
         FPR: FPR8
     }
 
 
 def map_regs_norex(regs):
     # type: (Sequence[OperandConstraint]) -> Sequence[OperandConstraint]
     return tuple(NOREX_MAP.get(rc, rc) if isinstance(rc, RegClass) else rc
                  for rc in regs)
@@ -149,76 +150,73 @@ class TailRecipe:
     `EncRecipe` does it. Additionally, the text `PUT_OP` is substituted with
     the proper `put_*` function from the `x86/binemit.rs` module.
     """
 
     def __init__(
             self,
             name,                   # type: str
             format,                 # type: InstructionFormat
-            base_size,              # type: int
+            size,                   # type: int
             ins,                    # type: ConstraintSeq
             outs,                   # type: ConstraintSeq
             branch_range=None,      # type: int
             clobbers_flags=True,    # type: bool
             instp=None,             # type: PredNode
             isap=None,              # type: PredNode
             when_prefixed=None,     # type: TailRecipe
             requires_prefix=False,  # type: bool
-            emit=None,              # type: str
-            compute_size=None       # type: str
+            emit=None               # type: str
             ):
         # type: (...) -> None
         self.name = name
         self.format = format
-        self.base_size = base_size
+        self.size = size
         self.ins = ins
         self.outs = outs
         self.branch_range = branch_range
         self.clobbers_flags = clobbers_flags
         self.instp = instp
         self.isap = isap
         self.when_prefixed = when_prefixed
         self.requires_prefix = requires_prefix
         self.emit = emit
-        self.compute_size = compute_size
 
         # Cached recipes, keyed by name prefix.
         self.recipes = dict()  # type: Dict[str, EncRecipe]
 
     def __call__(self, *ops, **kwargs):
         # type: (*int, **int) -> Tuple[EncRecipe, int]
         """
         Create an encoding recipe and encoding bits for the opcode bytes in
         `ops`.
         """
         assert not self.requires_prefix, "Tail recipe requires REX prefix."
         rrr = kwargs.get('rrr', 0)
         w = kwargs.get('w', 0)
         name, bits = decode_ops(ops, rrr, w)
-        base_size = len(ops) + self.base_size
+        size = len(ops) + self.size
 
         # All branch ranges are relative to the end of the instruction.
         branch_range = None  # type BranchRange
         if self.branch_range is not None:
-            branch_range = (base_size, self.branch_range)
+            branch_range = (size, self.branch_range)
 
         if name not in self.recipes:
             recipe = EncRecipe(
                 name + self.name,
                 self.format,
-                base_size,
+                size,
                 ins=self.ins,
                 outs=self.outs,
                 branch_range=branch_range,
                 clobbers_flags=self.clobbers_flags,
                 instp=self.instp,
                 isap=self.isap,
-                emit=replace_put_op(self.emit, name),
-                compute_size=self.compute_size)
+                emit=replace_put_op(self.emit, name))
 
             recipe.ins = map_regs_norex(recipe.ins)
             recipe.outs = map_regs_norex(recipe.outs)
             self.recipes[name] = recipe
         return (self.recipes[name], bits)
 
     def rex(self, *ops, **kwargs):
         # type: (*int, **int) -> Tuple[EncRecipe, int]
@@ -233,36 +231,35 @@ class TailRecipe:
         # Use the prefixed alternative recipe when applicable.
         if self.when_prefixed:
             return self.when_prefixed.rex(*ops, **kwargs)
 
         rrr = kwargs.get('rrr', 0)
         w = kwargs.get('w', 0)
         name, bits = decode_ops(ops, rrr, w)
         name = 'Rex' + name
-        base_size = 1 + len(ops) + self.base_size
+        size = 1 + len(ops) + self.size
 
         # All branch ranges are relative to the end of the instruction.
         branch_range = None  # type BranchRange
         if self.branch_range is not None:
-            branch_range = (base_size, self.branch_range)
+            branch_range = (size, self.branch_range)
 
         if name not in self.recipes:
             recipe = EncRecipe(
                 name + self.name,
                 self.format,
-                base_size,
+                size,
                 ins=self.ins,
                 outs=self.outs,
                 branch_range=branch_range,
                 clobbers_flags=self.clobbers_flags,
                 instp=self.instp,
                 isap=self.isap,
-                emit=replace_put_op(self.emit, name),
-                compute_size=self.compute_size)
+                emit=replace_put_op(self.emit, name))
             self.recipes[name] = recipe
 
         return (self.recipes[name], bits)
 
     @staticmethod
     def check_names(globs):
         # type: (Dict[str, Any]) -> None
         for name, obj in globs.items():
@@ -274,492 +271,480 @@ def floatccs(iform):
     # type: (InstructionFormat) -> PredNode
     """
     Return an instruction predicate that checks in `iform.cond` is one of the
     directly supported floating point condition codes.
     """
     return Or(*(IsEqual(iform.cond, cc) for cc in supported_floatccs))
 
 
-def valid_scale(iform):
-    # type: (InstructionFormat) -> PredNode
-    """
-    Return an instruction predicate that checks if `iform.imm` is a valid
-    `scale` for a SIB byte.
-    """
-    return Or(IsEqual(iform.imm, 1),
-              IsEqual(iform.imm, 2),
-              IsEqual(iform.imm, 4),
-              IsEqual(iform.imm, 8))
-
-
 # A null unary instruction that takes a GPR register. Can be used for identity
 # copies and no-op conversions.
-null = EncRecipe('null', Unary, base_size=0, ins=GPR, outs=0, emit='')
+null = EncRecipe('null', Unary, size=0, ins=GPR, outs=0, emit='')
 
 # XX opcode, no ModR/M.
 trap = TailRecipe(
-        'trap', Trap, base_size=0, ins=(), outs=(),
+        'trap', Trap, size=0, ins=(), outs=(),
         emit='''
         sink.trap(code, func.srclocs[inst]);
         PUT_OP(bits, BASE_REX, sink);
         ''')
 
 # Macro: conditional jump over a ud2.
 trapif = EncRecipe(
-        'trapif', IntCondTrap, base_size=4, ins=FLAG.rflags, outs=(),
+        'trapif', IntCondTrap, size=4, ins=FLAG.rflags, outs=(),
         clobbers_flags=False,
         emit='''
         // Jump over a 2-byte ud2.
         sink.put1(0x70 | (icc2opc(cond.inverse()) as u8));
         sink.put1(2);
         // ud2.
         sink.trap(code, func.srclocs[inst]);
         sink.put1(0x0f);
         sink.put1(0x0b);
         ''')
 
 trapff = EncRecipe(
-        'trapff', FloatCondTrap, base_size=4, ins=FLAG.rflags, outs=(),
+        'trapff', FloatCondTrap, size=4, ins=FLAG.rflags, outs=(),
         clobbers_flags=False,
         instp=floatccs(FloatCondTrap),
         emit='''
         // Jump over a 2-byte ud2.
         sink.put1(0x70 | (fcc2opc(cond.inverse()) as u8));
         sink.put1(2);
         // ud2.
         sink.trap(code, func.srclocs[inst]);
         sink.put1(0x0f);
         sink.put1(0x0b);
         ''')
 
 
 # XX /r
 rr = TailRecipe(
-        'rr', Binary, base_size=1, ins=(GPR, GPR), outs=0,
+        'rr', Binary, size=1, ins=(GPR, GPR), outs=0,
         emit='''
         PUT_OP(bits, rex2(in_reg0, in_reg1), sink);
         modrm_rr(in_reg0, in_reg1, sink);
         ''')
 
 # XX /r with operands swapped. (RM form).
 rrx = TailRecipe(
-        'rrx', Binary, base_size=1, ins=(GPR, GPR), outs=0,
+        'rrx', Binary, size=1, ins=(GPR, GPR), outs=0,
         emit='''
         PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
         modrm_rr(in_reg1, in_reg0, sink);
         ''')
 
 # XX /r with FPR ins and outs. A form.
 fa = TailRecipe(
-        'fa', Binary, base_size=1, ins=(FPR, FPR), outs=0,
+        'fa', Binary, size=1, ins=(FPR, FPR), outs=0,
         emit='''
         PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
         modrm_rr(in_reg1, in_reg0, sink);
         ''')
 
 # XX /r with FPR ins and outs. A form with input operands swapped.
 fax = TailRecipe(
-        'fax', Binary, base_size=1, ins=(FPR, FPR), outs=1,
+        'fax', Binary, size=1, ins=(FPR, FPR), outs=1,
         emit='''
         PUT_OP(bits, rex2(in_reg0, in_reg1), sink);
         modrm_rr(in_reg0, in_reg1, sink);
         ''')
 
 # XX /n for a unary operation with extension bits.
 ur = TailRecipe(
-        'ur', Unary, base_size=1, ins=GPR, outs=0,
+        'ur', Unary, size=1, ins=GPR, outs=0,
         emit='''
         PUT_OP(bits, rex1(in_reg0), sink);
         modrm_r_bits(in_reg0, bits, sink);
         ''')
 
 # XX /r, but for a unary operator with separate input/output register, like
 # copies. MR form, preserving flags.
 umr = TailRecipe(
-        'umr', Unary, base_size=1, ins=GPR, outs=GPR,
+        'umr', Unary, size=1, ins=GPR, outs=GPR,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits, rex2(out_reg0, in_reg0), sink);
         modrm_rr(out_reg0, in_reg0, sink);
         ''')
 
 # Same as umr, but with FPR -> GPR registers.
 rfumr = TailRecipe(
-        'rfumr', Unary, base_size=1, ins=FPR, outs=GPR,
+        'rfumr', Unary, size=1, ins=FPR, outs=GPR,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits, rex2(out_reg0, in_reg0), sink);
         modrm_rr(out_reg0, in_reg0, sink);
         ''')
 
 # XX /r, but for a unary operator with separate input/output register.
 # RM form. Clobbers FLAGS.
 urm = TailRecipe(
-        'urm', Unary, base_size=1, ins=GPR, outs=GPR,
+        'urm', Unary, size=1, ins=GPR, outs=GPR,
         emit='''
         PUT_OP(bits, rex2(in_reg0, out_reg0), sink);
         modrm_rr(in_reg0, out_reg0, sink);
         ''')
 
 # XX /r. Same as urm, but doesn't clobber FLAGS.
 urm_noflags = TailRecipe(
-        'urm_noflags', Unary, base_size=1, ins=GPR, outs=GPR,
+        'urm_noflags', Unary, size=1, ins=GPR, outs=GPR,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits, rex2(in_reg0, out_reg0), sink);
         modrm_rr(in_reg0, out_reg0, sink);
         ''')
 
 # XX /r. Same as urm_noflags, but input limited to ABCD.
 urm_noflags_abcd = TailRecipe(
-        'urm_noflags_abcd', Unary, base_size=1, ins=ABCD, outs=GPR,
+        'urm_noflags_abcd', Unary, size=1, ins=ABCD, outs=GPR,
         when_prefixed=urm_noflags,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits, rex2(in_reg0, out_reg0), sink);
         modrm_rr(in_reg0, out_reg0, sink);
         ''')
 
 # XX /r, RM form, FPR -> FPR.
 furm = TailRecipe(
-        'furm', Unary, base_size=1, ins=FPR, outs=FPR,
+        'furm', Unary, size=1, ins=FPR, outs=FPR,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits, rex2(in_reg0, out_reg0), sink);
         modrm_rr(in_reg0, out_reg0, sink);
         ''')
 
 # XX /r, RM form, GPR -> FPR.
 frurm = TailRecipe(
-        'frurm', Unary, base_size=1, ins=GPR, outs=FPR,
+        'frurm', Unary, size=1, ins=GPR, outs=FPR,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits, rex2(in_reg0, out_reg0), sink);
         modrm_rr(in_reg0, out_reg0, sink);
         ''')
 
 # XX /r, RM form, FPR -> GPR.
 rfurm = TailRecipe(
-        'rfurm', Unary, base_size=1, ins=FPR, outs=GPR,
+        'rfurm', Unary, size=1, ins=FPR, outs=GPR,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits, rex2(in_reg0, out_reg0), sink);
         modrm_rr(in_reg0, out_reg0, sink);
         ''')
 
 # XX /r, RMI form for one of the roundXX SSE 4.1 instructions.
 furmi_rnd = TailRecipe(
-        'furmi_rnd', Unary, base_size=2, ins=FPR, outs=FPR,
+        'furmi_rnd', Unary, size=2, ins=FPR, outs=FPR,
         isap=use_sse41,
         emit='''
         PUT_OP(bits, rex2(in_reg0, out_reg0), sink);
         modrm_rr(in_reg0, out_reg0, sink);
         sink.put1(match opcode {
             Opcode::Nearest => 0b00,
             Opcode::Floor => 0b01,
             Opcode::Ceil => 0b10,
             Opcode::Trunc => 0b11,
             x => panic!("{} unexpected for furmi_rnd", opcode),
         });
         ''')
 
 # XX /r, for regmove instructions.
 rmov = TailRecipe(
-        'rmov', RegMove, base_size=1, ins=GPR, outs=(),
+        'rmov', RegMove, size=1, ins=GPR, outs=(),
         clobbers_flags=False,
         emit='''
         PUT_OP(bits, rex2(dst, src), sink);
         modrm_rr(dst, src, sink);
         ''')
 
 # XX /r, for regmove instructions (FPR version, RM encoded).
 frmov = TailRecipe(
-        'frmov', RegMove, base_size=1, ins=FPR, outs=(),
+        'frmov', RegMove, size=1, ins=FPR, outs=(),
         clobbers_flags=False,
         emit='''
         PUT_OP(bits, rex2(src, dst), sink);
         modrm_rr(src, dst, sink);
         ''')
 
 # XX /n with one arg in %rcx, for shifts.
 rc = TailRecipe(
-        'rc', Binary, base_size=1, ins=(GPR, GPR.rcx), outs=0,
+        'rc', Binary, size=1, ins=(GPR, GPR.rcx), outs=0,
         emit='''
         PUT_OP(bits, rex1(in_reg0), sink);
         modrm_r_bits(in_reg0, bits, sink);
         ''')
 
 # XX /n for division: inputs in %rax, %rdx, r. Outputs in %rax, %rdx.
 div = TailRecipe(
-        'div', Ternary, base_size=1,
+        'div', Ternary, size=1,
         ins=(GPR.rax, GPR.rdx, GPR), outs=(GPR.rax, GPR.rdx),
         emit='''
         sink.trap(TrapCode::IntegerDivisionByZero, func.srclocs[inst]);
         PUT_OP(bits, rex1(in_reg2), sink);
         modrm_r_bits(in_reg2, bits, sink);
         ''')
 
 # XX /n for {s,u}mulx: inputs in %rax, r. Outputs in %rdx(hi):%rax(lo)
 mulx = TailRecipe(
-        'mulx', Binary, base_size=1,
+        'mulx', Binary, size=1,
         ins=(GPR.rax, GPR), outs=(GPR.rax, GPR.rdx),
         emit='''
         PUT_OP(bits, rex1(in_reg1), sink);
         modrm_r_bits(in_reg1, bits, sink);
         ''')
 
 # XX /n ib with 8-bit immediate sign-extended.
 r_ib = TailRecipe(
-        'r_ib', BinaryImm, base_size=2, ins=GPR, outs=0,
+        'r_ib', BinaryImm, size=2, ins=GPR, outs=0,
         instp=IsSignedInt(BinaryImm.imm, 8),
         emit='''
         PUT_OP(bits, rex1(in_reg0), sink);
         modrm_r_bits(in_reg0, bits, sink);
         let imm: i64 = imm.into();
         sink.put1(imm as u8);
         ''')
 
 # XX /n id with 32-bit immediate sign-extended.
 r_id = TailRecipe(
-        'r_id', BinaryImm, base_size=5, ins=GPR, outs=0,
+        'r_id', BinaryImm, size=5, ins=GPR, outs=0,
         instp=IsSignedInt(BinaryImm.imm, 32),
         emit='''
         PUT_OP(bits, rex1(in_reg0), sink);
         modrm_r_bits(in_reg0, bits, sink);
         let imm: i64 = imm.into();
         sink.put4(imm as u32);
         ''')
 
 # XX /n id with 32-bit immediate sign-extended. UnaryImm version.
 u_id = TailRecipe(
-        'u_id', UnaryImm, base_size=5, ins=(), outs=GPR,
+        'u_id', UnaryImm, size=5, ins=(), outs=GPR,
         instp=IsSignedInt(UnaryImm.imm, 32),
         emit='''
         PUT_OP(bits, rex1(out_reg0), sink);
         modrm_r_bits(out_reg0, bits, sink);
         let imm: i64 = imm.into();
         sink.put4(imm as u32);
         ''')
 
 # XX+rd id unary with 32-bit immediate. Note no recipe predicate.
 pu_id = TailRecipe(
-        'pu_id', UnaryImm, base_size=4, ins=(), outs=GPR,
+        'pu_id', UnaryImm, size=4, ins=(), outs=GPR,
         emit='''
         // The destination register is encoded in the low bits of the opcode.
         // No ModR/M.
         PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
         let imm: i64 = imm.into();
         sink.put4(imm as u32);
         ''')
 
 # XX+rd id unary with bool immediate. Note no recipe predicate.
 pu_id_bool = TailRecipe(
-        'pu_id_bool', UnaryBool, base_size=4, ins=(), outs=GPR,
+        'pu_id_bool', UnaryBool, size=4, ins=(), outs=GPR,
         emit='''
         // The destination register is encoded in the low bits of the opcode.
         // No ModR/M.
         PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
         let imm: u32 = if imm { 1 } else { 0 };
         sink.put4(imm);
         ''')
 
 # XX+rd iq unary with 64-bit immediate.
 pu_iq = TailRecipe(
-        'pu_iq', UnaryImm, base_size=8, ins=(), outs=GPR,
+        'pu_iq', UnaryImm, size=8, ins=(), outs=GPR,
         emit='''
         PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
         let imm: i64 = imm.into();
         sink.put8(imm as u64);
         ''')
 
 # XX /n Unary with floating point 32-bit immediate equal to zero.
 f32imm_z = TailRecipe(
-    'f32imm_z', UnaryIeee32, base_size=1, ins=(), outs=FPR,
+    'f32imm_z', UnaryIeee32, size=1, ins=(), outs=FPR,
     instp=IsZero32BitFloat(UnaryIeee32.imm),
     emit='''
         PUT_OP(bits, rex2(out_reg0, out_reg0), sink);
         modrm_rr(out_reg0, out_reg0, sink);
     ''')
 
 # XX /n Unary with floating point 64-bit immediate equal to zero.
 f64imm_z = TailRecipe(
-    'f64imm_z', UnaryIeee64, base_size=1, ins=(), outs=FPR,
+    'f64imm_z', UnaryIeee64, size=1, ins=(), outs=FPR,
     instp=IsZero64BitFloat(UnaryIeee64.imm),
     emit='''
         PUT_OP(bits, rex2(out_reg0, out_reg0), sink);
         modrm_rr(out_reg0, out_reg0, sink);
     ''')
 
 pushq = TailRecipe(
-    'pushq', Unary, base_size=0, ins=GPR, outs=(),
+    'pushq', Unary, size=0, ins=GPR, outs=(),
     emit='''
     sink.trap(TrapCode::StackOverflow, func.srclocs[inst]);
     PUT_OP(bits | (in_reg0 & 7), rex1(in_reg0), sink);
     ''')
 
 popq = TailRecipe(
-    'popq', NullAry, base_size=0, ins=(), outs=GPR,
+    'popq', NullAry, size=0, ins=(), outs=GPR,
     emit='''
     PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
     ''')
 
 # XX /r, for regmove instructions.
 copysp = TailRecipe(
-        'copysp', CopySpecial, base_size=1, ins=(), outs=(),
+        'copysp', CopySpecial, size=1, ins=(), outs=(),
         clobbers_flags=False,
         emit='''
         PUT_OP(bits, rex2(dst, src), sink);
         modrm_rr(dst, src, sink);
         ''')
 
 adjustsp = TailRecipe(
-    'adjustsp', Unary, base_size=1, ins=(GPR), outs=(),
+    'adjustsp', Unary, size=1, ins=(GPR), outs=(),
     emit='''
     PUT_OP(bits, rex2(RU::rsp.into(), in_reg0), sink);
     modrm_rr(RU::rsp.into(), in_reg0, sink);
     ''')
 
 adjustsp_ib = TailRecipe(
-    'adjustsp_ib', UnaryImm, base_size=2, ins=(), outs=(),
+    'adjustsp_ib', UnaryImm, size=2, ins=(), outs=(),
     instp=IsSignedInt(UnaryImm.imm, 8),
     emit='''
     PUT_OP(bits, rex1(RU::rsp.into()), sink);
     modrm_r_bits(RU::rsp.into(), bits, sink);
     let imm: i64 = imm.into();
     sink.put1(imm as u8);
     ''')
 
 adjustsp_id = TailRecipe(
-    'adjustsp_id', UnaryImm, base_size=5, ins=(), outs=(),
+    'adjustsp_id', UnaryImm, size=5, ins=(), outs=(),
     instp=IsSignedInt(UnaryImm.imm, 32),
     emit='''
     PUT_OP(bits, rex1(RU::rsp.into()), sink);
     modrm_r_bits(RU::rsp.into(), bits, sink);
     let imm: i64 = imm.into();
     sink.put4(imm as u32);
     ''')
 
 
 # XX+rd id with Abs4 function relocation.
 fnaddr4 = TailRecipe(
-        'fnaddr4', FuncAddr, base_size=4, ins=(), outs=GPR,
+        'fnaddr4', FuncAddr, size=4, ins=(), outs=GPR,
         emit='''
         PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
         sink.reloc_external(Reloc::Abs4,
                             &func.dfg.ext_funcs[func_ref].name,
                             0);
         sink.put4(0);
         ''')
 
 # XX+rd iq with Abs8 function relocation.
 fnaddr8 = TailRecipe(
-        'fnaddr8', FuncAddr, base_size=8, ins=(), outs=GPR,
+        'fnaddr8', FuncAddr, size=8, ins=(), outs=GPR,
         emit='''
         PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
         sink.reloc_external(Reloc::Abs8,
                             &func.dfg.ext_funcs[func_ref].name,
                             0);
         sink.put8(0);
         ''')
 
 # Similar to fnaddr4, but writes !0 (this is used by BaldrMonkey).
 allones_fnaddr4 = TailRecipe(
-        'allones_fnaddr4', FuncAddr, base_size=4, ins=(), outs=GPR,
+        'allones_fnaddr4', FuncAddr, size=4, ins=(), outs=GPR,
         emit='''
         PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
         sink.reloc_external(Reloc::Abs4,
                             &func.dfg.ext_funcs[func_ref].name,
                             0);
         // Write the immediate as `!0` for the benefit of BaldrMonkey.
         sink.put4(!0);
         ''')
 
 # Similar to fnaddr8, but writes !0 (this is used by BaldrMonkey).
 allones_fnaddr8 = TailRecipe(
-        'allones_fnaddr8', FuncAddr, base_size=8, ins=(), outs=GPR,
+        'allones_fnaddr8', FuncAddr, size=8, ins=(), outs=GPR,
         emit='''
         PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
         sink.reloc_external(Reloc::Abs8,
                             &func.dfg.ext_funcs[func_ref].name,
                             0);
         // Write the immediate as `!0` for the benefit of BaldrMonkey.
         sink.put8(!0);
         ''')
 
 pcrel_fnaddr8 = TailRecipe(
-        'pcrel_fnaddr8', FuncAddr, base_size=5, ins=(), outs=GPR,
+        'pcrel_fnaddr8', FuncAddr, size=5, ins=(), outs=GPR,
         # rex2 gets passed 0 for r/m register because the upper bit of
         # r/m doesnt get decoded when in rip-relative addressing mode.
         emit='''
         PUT_OP(bits, rex2(0, out_reg0), sink);
         modrm_riprel(out_reg0, sink);
         // The addend adjusts for the difference between the end of the
         // instruction and the beginning of the immediate field.
         sink.reloc_external(Reloc::X86PCRel4,
                             &func.dfg.ext_funcs[func_ref].name,
                             -4);
         sink.put4(0);
         ''')
 
 got_fnaddr8 = TailRecipe(
-        'got_fnaddr8', FuncAddr, base_size=5, ins=(), outs=GPR,
+        'got_fnaddr8', FuncAddr, size=5, ins=(), outs=GPR,
         # rex2 gets passed 0 for r/m register because the upper bit of
         # r/m doesnt get decoded when in rip-relative addressing mode.
         emit='''
         PUT_OP(bits, rex2(0, out_reg0), sink);
         modrm_riprel(out_reg0, sink);
         // The addend adjusts for the difference between the end of the
         // instruction and the beginning of the immediate field.
         sink.reloc_external(Reloc::X86GOTPCRel4,
                             &func.dfg.ext_funcs[func_ref].name,
                             -4);
         sink.put4(0);
         ''')
 
 
 # XX+rd id with Abs4 globalsym relocation.
 gvaddr4 = TailRecipe(
-        'gvaddr4', UnaryGlobalValue, base_size=4, ins=(), outs=GPR,
+        'gvaddr4', UnaryGlobalValue, size=4, ins=(), outs=GPR,
         emit='''
         PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
         sink.reloc_external(Reloc::Abs4,
                             &func.global_values[global_value].symbol_name(),
                             0);
         sink.put4(0);
         ''')
 
 # XX+rd iq with Abs8 globalsym relocation.
 gvaddr8 = TailRecipe(
-        'gvaddr8', UnaryGlobalValue, base_size=8, ins=(), outs=GPR,
+        'gvaddr8', UnaryGlobalValue, size=8, ins=(), outs=GPR,
         emit='''
         PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
         sink.reloc_external(Reloc::Abs8,
                             &func.global_values[global_value].symbol_name(),
                             0);
         sink.put8(0);
         ''')
 
 # XX+rd iq with PCRel4 globalsym relocation.
 pcrel_gvaddr8 = TailRecipe(
-        'pcrel_gvaddr8', UnaryGlobalValue, base_size=5, ins=(), outs=GPR,
+        'pcrel_gvaddr8', UnaryGlobalValue, size=5, ins=(), outs=GPR,
         emit='''
         PUT_OP(bits, rex2(0, out_reg0), sink);
         modrm_rm(5, out_reg0, sink);
         // The addend adjusts for the difference between the end of the
         // instruction and the beginning of the immediate field.
         sink.reloc_external(Reloc::X86PCRel4,
                             &func.global_values[global_value].symbol_name(),
                             -4);
         sink.put4(0);
         ''')
 
 # XX+rd iq with Abs8 globalsym relocation.
 got_gvaddr8 = TailRecipe(
-        'got_gvaddr8', UnaryGlobalValue, base_size=5, ins=(), outs=GPR,
+        'got_gvaddr8', UnaryGlobalValue, size=5, ins=(), outs=GPR,
         emit='''
         PUT_OP(bits, rex2(0, out_reg0), sink);
         modrm_rm(5, out_reg0, sink);
         // The addend adjusts for the difference between the end of the
         // instruction and the beginning of the immediate field.
         sink.reloc_external(Reloc::X86GOTPCRel4,
                             &func.global_values[global_value].symbol_name(),
                             -4);
@@ -768,29 +753,29 @@ got_gvaddr8 = TailRecipe(
 
 #
 # Stack addresses.
 #
 # TODO: Alternative forms for 8-bit immediates, when applicable.
 #
 
 spaddr4_id = TailRecipe(
-        'spaddr4_id', StackLoad, base_size=6, ins=(), outs=GPR,
+        'spaddr4_id', StackLoad, size=6, ins=(), outs=GPR,
         emit='''
         let sp = StackRef::sp(stack_slot, &func.stack_slots);
         let base = stk_base(sp.base);
         PUT_OP(bits, rex2(out_reg0, base), sink);
         modrm_sib_disp8(out_reg0, sink);
         sib_noindex(base, sink);
         let imm : i32 = offset.into();
         sink.put4(sp.offset.checked_add(imm).unwrap() as u32);
         ''')
 
 spaddr8_id = TailRecipe(
-        'spaddr8_id', StackLoad, base_size=6, ins=(), outs=GPR,
+        'spaddr8_id', StackLoad, size=6, ins=(), outs=GPR,
         emit='''
         let sp = StackRef::sp(stack_slot, &func.stack_slots);
         let base = stk_base(sp.base);
         PUT_OP(bits, rex2(base, out_reg0), sink);
         modrm_sib_disp32(out_reg0, sink);
         sib_noindex(base, sink);
         let imm : i32 = offset.into();
         sink.put4(sp.offset.checked_add(imm).unwrap() as u32);
@@ -798,160 +783,121 @@ spaddr8_id = TailRecipe(
 
 
 #
 # Store recipes.
 #
 
 # XX /r register-indirect store with no offset.
 st = TailRecipe(
-        'st', Store, base_size=1, ins=(GPR, GPR), outs=(),
+        'st', Store, size=1, ins=(GPR, GPR_ZERO_DEREF_SAFE), outs=(),
         instp=IsEqual(Store.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, rex2(in_reg1, in_reg0), sink);
-        if needs_offset(in_reg1) {
-            modrm_disp8(in_reg1, in_reg0, sink);
-            sink.put1(0);
-        } else {
-            modrm_rm(in_reg1, in_reg0, sink);
-        }
+        modrm_rm(in_reg1, in_reg0, sink);
         ''')
 
 # XX /r register-indirect store with index and no offset.
 stWithIndex = TailRecipe(
-    'stWithIndex', StoreComplex, base_size=2,
-    ins=(GPR, GPR, GPR),
+    'stWithIndex', StoreComplex, size=2,
+    ins=(GPR, GPR_ZERO_DEREF_SAFE, GPR_DEREF_SAFE),
     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);
-    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);
-    }
+    modrm_sib(in_reg0, sink);
+    sib(0, in_reg2, in_reg1, sink);
     ''')
 
 # 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=(),
+        'st_abcd', Store, size=1, ins=(ABCD, GPR), outs=(),
         instp=IsEqual(Store.offset, 0),
         when_prefixed=st,
         clobbers_flags=False,
         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);
         ''')
 
 # 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),
+    'stWithIndex_abcd', StoreComplex, size=2,
+    ins=(ABCD, GPR_ZERO_DEREF_SAFE, GPR_DEREF_SAFE),
     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);
-    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);
-    }
+    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=(),
+        'fst', Store, size=1, ins=(FPR, GPR_ZERO_DEREF_SAFE), outs=(),
         instp=IsEqual(Store.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, rex2(in_reg1, in_reg0), sink);
-        if needs_offset(in_reg1) {
-            modrm_disp8(in_reg1, in_reg0, sink);
-            sink.put1(0);
-        } else {
-            modrm_rm(in_reg1, in_reg0, sink);
-        }
+        modrm_rm(in_reg1, in_reg0, sink);
         ''')
 # XX /r register-indirect store with index and no offset of FPR.
 fstWithIndex = TailRecipe(
-        'fstWithIndex', StoreComplex, base_size=2,
-        ins=(FPR, GPR, GPR), outs=(),
+        'fstWithIndex', StoreComplex, size=2,
+        ins=(FPR, GPR_ZERO_DEREF_SAFE, GPR_DEREF_SAFE), 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);
-        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);
-        }
+        modrm_sib(in_reg0, sink);
+        sib(0, in_reg2, in_reg1, sink);
         ''')
 
 # XX /r register-indirect store with 8-bit offset.
 stDisp8 = TailRecipe(
-        'stDisp8', Store, base_size=2, ins=(GPR, GPR), outs=(),
+        'stDisp8', Store, size=2, ins=(GPR, GPR_DEREF_SAFE), outs=(),
         instp=IsSignedInt(Store.offset, 8),
         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);
-        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);
-        }
+        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.
 stWithIndexDisp8 = TailRecipe(
-    'stWithIndexDisp8', StoreComplex, base_size=3,
-    ins=(GPR, GPR, GPR),
+    'stWithIndexDisp8', StoreComplex, size=3,
+    ins=(GPR, GPR, GPR_DEREF_SAFE),
     outs=(),
     instp=IsSignedInt(StoreComplex.offset, 8),
     clobbers_flags=False,
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg1, in_reg0, in_reg2), sink);
@@ -959,112 +905,100 @@ stWithIndexDisp8 = TailRecipe(
     sib(0, in_reg2, in_reg1, sink);
     let offset: i32 = offset.into();
     sink.put1(offset as u8);
     ''')
 
 # 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=(),
+        'stDisp8_abcd', Store, size=2, ins=(ABCD, GPR), outs=(),
         instp=IsSignedInt(Store.offset, 8),
         when_prefixed=stDisp8,
         clobbers_flags=False,
         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);
         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,
-    ins=(ABCD, GPR, GPR),
+    'stWithIndexDisp8_abcd', StoreComplex, size=3,
+    ins=(ABCD, GPR, GPR_DEREF_SAFE),
     outs=(),
     instp=IsSignedInt(StoreComplex.offset, 8),
     clobbers_flags=False,
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg1, in_reg0, in_reg2), sink);
     modrm_sib_disp8(in_reg0, sink);
     sib(0, in_reg2, in_reg1, sink);
     let offset: i32 = offset.into();
     sink.put1(offset as u8);
     ''')
 
 # XX /r register-indirect store with 8-bit offset of FPR.
 fstDisp8 = TailRecipe(
-        'fstDisp8', Store, base_size=2, ins=(FPR, GPR), outs=(),
+        'fstDisp8', Store, size=2, ins=(FPR, GPR_DEREF_SAFE), outs=(),
         instp=IsSignedInt(Store.offset, 8),
         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);
-        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);
-        }
+        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 of FPR.
 fstWithIndexDisp8 = TailRecipe(
-    'fstWithIndexDisp8', StoreComplex, base_size=3,
-    ins=(FPR, GPR, GPR),
+    'fstWithIndexDisp8', StoreComplex, size=3,
+    ins=(FPR, GPR, GPR_DEREF_SAFE),
     outs=(),
     instp=IsSignedInt(StoreComplex.offset, 8),
     clobbers_flags=False,
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg1, in_reg0, in_reg2), sink);
     modrm_sib_disp8(in_reg0, sink);
     sib(0, in_reg2, in_reg1, sink);
     let offset: i32 = offset.into();
     sink.put1(offset as u8);
     ''')
 
 # XX /r register-indirect store with 32-bit offset.
 stDisp32 = TailRecipe(
-        'stDisp32', Store, base_size=5, ins=(GPR, GPR), outs=(),
+        'stDisp32', Store, size=5, ins=(GPR, GPR_DEREF_SAFE), outs=(),
         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);
-        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);
-        }
+        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.
 stWithIndexDisp32 = TailRecipe(
-    'stWithIndexDisp32', StoreComplex, base_size=6,
-    ins=(GPR, GPR, GPR),
+    'stWithIndexDisp32', StoreComplex, size=6,
+    ins=(GPR, GPR, GPR_DEREF_SAFE),
     outs=(),
     instp=IsSignedInt(StoreComplex.offset, 32),
     clobbers_flags=False,
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg1, in_reg0, in_reg2), sink);
@@ -1072,129 +1006,123 @@ stWithIndexDisp32 = TailRecipe(
     sib(0, in_reg2, in_reg1, sink);
     let offset: i32 = offset.into();
     sink.put4(offset as u32);
     ''')
 
 # 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=(),
+        'stDisp32_abcd', Store, size=5, ins=(ABCD, GPR), outs=(),
         when_prefixed=stDisp32,
         clobbers_flags=False,
         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);
         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,
-    ins=(ABCD, GPR, GPR),
+    'stWithIndexDisp32_abcd', StoreComplex, size=6,
+    ins=(ABCD, GPR, GPR_DEREF_SAFE),
     outs=(),
     instp=IsSignedInt(StoreComplex.offset, 32),
     clobbers_flags=False,
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg1, in_reg0, in_reg2), sink);
     modrm_sib_disp32(in_reg0, sink);
     sib(0, in_reg2, in_reg1, sink);
     let offset: i32 = offset.into();
     sink.put4(offset as u32);
     ''')
 
 # XX /r register-indirect store with 32-bit offset of FPR.
 fstDisp32 = TailRecipe(
-        'fstDisp32', Store, base_size=5, ins=(FPR, GPR), outs=(),
+        'fstDisp32', Store, size=5, ins=(FPR, GPR_DEREF_SAFE), outs=(),
         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);
-        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);
-        }
+        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 of FPR.
 fstWithIndexDisp32 = TailRecipe(
-    'fstWithIndexDisp32', StoreComplex, base_size=6,
-    ins=(FPR, GPR, GPR),
+    'fstWithIndexDisp32', StoreComplex, size=6,
+    ins=(FPR, GPR, GPR_DEREF_SAFE),
     outs=(),
     instp=IsSignedInt(StoreComplex.offset, 32),
     clobbers_flags=False,
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg1, in_reg0, in_reg2), sink);
     modrm_sib_disp32(in_reg0, sink);
     sib(0, in_reg2, in_reg1, sink);
     let offset: i32 = offset.into();
     sink.put4(offset as u32);
     ''')
 
 # Unary spill with SIB and 32-bit displacement.
 spillSib32 = TailRecipe(
-        'spillSib32', Unary, base_size=6, ins=GPR, outs=StackGPR32,
+        'spillSib32', Unary, size=6, ins=GPR, outs=StackGPR32,
         clobbers_flags=False,
         emit='''
         sink.trap(TrapCode::StackOverflow, func.srclocs[inst]);
         let base = stk_base(out_stk0.base);
         PUT_OP(bits, rex2(base, in_reg0), sink);
         modrm_sib_disp32(in_reg0, sink);
         sib_noindex(base, sink);
         sink.put4(out_stk0.offset as u32);
         ''')
 
 # Like spillSib32, but targeting an FPR rather than a GPR.
 fspillSib32 = TailRecipe(
-        'fspillSib32', Unary, base_size=6, ins=FPR, outs=StackFPR32,
+        'fspillSib32', Unary, size=6, ins=FPR, outs=StackFPR32,
         clobbers_flags=False,
         emit='''
         sink.trap(TrapCode::StackOverflow, func.srclocs[inst]);
         let base = stk_base(out_stk0.base);
         PUT_OP(bits, rex2(base, in_reg0), sink);
         modrm_sib_disp32(in_reg0, sink);
         sib_noindex(base, sink);
         sink.put4(out_stk0.offset as u32);
         ''')
 
 # Regspill using RSP-relative addressing.
 regspill32 = TailRecipe(
-        'regspill32', RegSpill, base_size=6, ins=GPR, outs=(),
+        'regspill32', RegSpill, size=6, ins=GPR, outs=(),
         clobbers_flags=False,
         emit='''
         sink.trap(TrapCode::StackOverflow, func.srclocs[inst]);
         let dst = StackRef::sp(dst, &func.stack_slots);
         let base = stk_base(dst.base);
         PUT_OP(bits, rex2(base, src), sink);
         modrm_sib_disp32(src, sink);
         sib_noindex(base, sink);
         sink.put4(dst.offset as u32);
         ''')
 
 # Like regspill32, but targeting an FPR rather than a GPR.
 fregspill32 = TailRecipe(
-        'fregspill32', RegSpill, base_size=6, ins=FPR, outs=(),
+        'fregspill32', RegSpill, size=6, ins=FPR, outs=(),
         clobbers_flags=False,
         emit='''
         sink.trap(TrapCode::StackOverflow, func.srclocs[inst]);
         let dst = StackRef::sp(dst, &func.stack_slots);
         let base = stk_base(dst.base);
         PUT_OP(bits, rex2(base, src), sink);
         modrm_sib_disp32(src, sink);
         sib_noindex(base, sink);
@@ -1202,558 +1130,469 @@ fregspill32 = TailRecipe(
         ''')
 
 #
 # Load recipes
 #
 
 # XX /r load with no offset.
 ld = TailRecipe(
-        'ld', Load, base_size=1, ins=(GPR), outs=(GPR),
+        'ld', Load, size=1, ins=(GPR_ZERO_DEREF_SAFE), outs=(GPR),
         instp=IsEqual(Load.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, rex2(in_reg0, out_reg0), sink);
-        if needs_offset(in_reg0) {
-            modrm_disp8(in_reg0, out_reg0, sink);
-            sink.put1(0);
-        } else {
-            modrm_rm(in_reg0, out_reg0, sink);
-        }
+        modrm_rm(in_reg0, out_reg0, sink);
         ''')
 
 # XX /r load with index and no offset.
 ldWithIndex = TailRecipe(
-    'ldWithIndex', LoadComplex, base_size=2,
-    ins=(GPR, GPR),
+    'ldWithIndex', LoadComplex, size=2,
+    ins=(GPR_ZERO_DEREF_SAFE, GPR_DEREF_SAFE),
     outs=(GPR),
     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);
-    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);
-    }
+    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),
+        'fld', Load, size=1, ins=(GPR_ZERO_DEREF_SAFE), outs=(FPR),
         instp=IsEqual(Load.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, rex2(in_reg0, out_reg0), sink);
-        if needs_offset(in_reg0) {
-            modrm_disp8(in_reg0, out_reg0, sink);
-            sink.put1(0);
-        } else {
-            modrm_rm(in_reg0, out_reg0, sink);
-        }
+        modrm_rm(in_reg0, out_reg0, sink);
         ''')
 
 # XX /r float load with index and no offset.
 fldWithIndex = TailRecipe(
-    'fldWithIndex', LoadComplex, base_size=2,
-    ins=(GPR, GPR),
+    'fldWithIndex', LoadComplex, size=2,
+    ins=(GPR_ZERO_DEREF_SAFE, GPR_DEREF_SAFE),
     outs=(FPR),
     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);
-    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);
-    }
+    modrm_sib(out_reg0, sink);
+    sib(0, in_reg1, in_reg0, sink);
     ''')
 
 # XX /r load with 8-bit offset.
 ldDisp8 = TailRecipe(
-        'ldDisp8', Load, base_size=2, ins=(GPR), outs=(GPR),
+        'ldDisp8', Load, size=2, ins=(GPR_DEREF_SAFE), outs=(GPR),
         instp=IsSignedInt(Load.offset, 8),
         clobbers_flags=False,
-        compute_size="size_plus_maybe_sib_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_sib_byte(in_reg0) {
-            modrm_sib_disp8(out_reg0, sink);
-            sib_noindex(in_reg0, sink);
-        } else {
-            modrm_disp8(in_reg0, out_reg0, sink);
-        }
+        modrm_disp8(in_reg0, out_reg0, sink);
         let offset: i32 = offset.into();
         sink.put1(offset as u8);
         ''')
 
 # XX /r load with index and 8-bit offset.
 ldWithIndexDisp8 = TailRecipe(
-    'ldWithIndexDisp8', LoadComplex, base_size=3,
-    ins=(GPR, GPR),
+    'ldWithIndexDisp8', LoadComplex, size=3,
+    ins=(GPR, GPR_DEREF_SAFE),
     outs=(GPR),
     instp=IsSignedInt(LoadComplex.offset, 8),
     clobbers_flags=False,
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg0, out_reg0, in_reg1), sink);
     modrm_sib_disp8(out_reg0, sink);
     sib(0, in_reg1, in_reg0, sink);
     let offset: i32 = offset.into();
     sink.put1(offset as u8);
     ''')
 
 # XX /r float load with 8-bit offset.
 fldDisp8 = TailRecipe(
-        'fldDisp8', Load, base_size=2, ins=(GPR), outs=(FPR),
+        'fldDisp8', Load, size=2, ins=(GPR_DEREF_SAFE), outs=(FPR),
         instp=IsSignedInt(Load.offset, 8),
         clobbers_flags=False,
-        compute_size="size_plus_maybe_sib_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_sib_byte(in_reg0) {
-            modrm_sib_disp8(out_reg0, sink);
-            sib_noindex(in_reg0, sink);
-        } else {
-            modrm_disp8(in_reg0, out_reg0, sink);
-        }
+        modrm_disp8(in_reg0, out_reg0, sink);
         let offset: i32 = offset.into();
         sink.put1(offset as u8);
         ''')
 
 # XX /r float load with 8-bit offset.
 fldWithIndexDisp8 = TailRecipe(
-    'fldWithIndexDisp8', LoadComplex, base_size=3,
-    ins=(GPR, GPR),
+    'fldWithIndexDisp8', LoadComplex, size=3,
+    ins=(GPR, GPR_DEREF_SAFE),
     outs=(FPR),
     instp=IsSignedInt(LoadComplex.offset, 8),
     clobbers_flags=False,
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg0, out_reg0, in_reg1), sink);
     modrm_sib_disp8(out_reg0, sink);
     sib(0, in_reg1, in_reg0, sink);
     let offset: i32 = offset.into();
     sink.put1(offset as u8);
     ''')
 
 # XX /r load with 32-bit offset.
 ldDisp32 = TailRecipe(
-        'ldDisp32', Load, base_size=5, ins=(GPR), outs=(GPR),
+        'ldDisp32', Load, size=5, ins=(GPR_DEREF_SAFE), outs=(GPR),
         instp=IsSignedInt(Load.offset, 32),
         clobbers_flags=False,
-        compute_size='size_plus_maybe_sib_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_sib_byte(in_reg0) {
-            modrm_sib_disp32(out_reg0, sink);
-            sib_noindex(in_reg0, sink);
-        } else {
-            modrm_disp32(in_reg0, out_reg0, sink);
-        }
+        modrm_disp32(in_reg0, out_reg0, sink);
         let offset: i32 = offset.into();
         sink.put4(offset as u32);
         ''')
 
 # XX /r load with index and 32-bit offset.
 ldWithIndexDisp32 = TailRecipe(
-    'ldWithIndexDisp32', LoadComplex, base_size=6,
-    ins=(GPR, GPR),
+    'ldWithIndexDisp32', LoadComplex, size=6,
+    ins=(GPR, GPR_DEREF_SAFE),
     outs=(GPR),
     instp=IsSignedInt(LoadComplex.offset, 32),
     clobbers_flags=False,
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg0, out_reg0, in_reg1), sink);
     modrm_sib_disp32(out_reg0, sink);
     sib(0, in_reg1, in_reg0, sink);
     let offset: i32 = offset.into();
     sink.put4(offset as u32);
     ''')
 
 # XX /r float load with 32-bit offset.
 fldDisp32 = TailRecipe(
-        'fldDisp32', Load, base_size=5, ins=(GPR), outs=(FPR),
+        'fldDisp32', Load, size=5, ins=(GPR_DEREF_SAFE), outs=(FPR),
         instp=IsSignedInt(Load.offset, 32),
         clobbers_flags=False,
-        compute_size="size_plus_maybe_sib_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_sib_byte(in_reg0) {
-            modrm_sib_disp32(out_reg0, sink);
-            sib_noindex(in_reg0, sink);
-        } else {
-            modrm_disp32(in_reg0, out_reg0, sink);
-        }
+        modrm_disp32(in_reg0, out_reg0, sink);
         let offset: i32 = offset.into();
         sink.put4(offset as u32);
         ''')
 
 # XX /r float load with index and 32-bit offset.
 fldWithIndexDisp32 = TailRecipe(
-    'fldWithIndexDisp32', LoadComplex, base_size=6,
-    ins=(GPR, GPR),
+    'fldWithIndexDisp32', LoadComplex, size=6,
+    ins=(GPR, GPR_DEREF_SAFE),
     outs=(FPR),
     instp=IsSignedInt(LoadComplex.offset, 32),
     clobbers_flags=False,
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg0, out_reg0, in_reg1), sink);
     modrm_sib_disp32(out_reg0, sink);
     sib(0, in_reg1, in_reg0, sink);
     let offset: i32 = offset.into();
     sink.put4(offset as u32);
     ''')
 
 # Unary fill with SIB and 32-bit displacement.
 fillSib32 = TailRecipe(
-        'fillSib32', Unary, base_size=6, ins=StackGPR32, outs=GPR,
+        'fillSib32', Unary, size=6, ins=StackGPR32, outs=GPR,
         clobbers_flags=False,
         emit='''
         let base = stk_base(in_stk0.base);
         PUT_OP(bits, rex2(base, out_reg0), sink);
         modrm_sib_disp32(out_reg0, sink);
         sib_noindex(base, sink);
         sink.put4(in_stk0.offset as u32);
         ''')
 
 # Like fillSib32, but targeting an FPR rather than a GPR.
 ffillSib32 = TailRecipe(
-        'ffillSib32', Unary, base_size=6, ins=StackFPR32, outs=FPR,
+        'ffillSib32', Unary, size=6, ins=StackFPR32, outs=FPR,
         clobbers_flags=False,
         emit='''
         let base = stk_base(in_stk0.base);
         PUT_OP(bits, rex2(base, out_reg0), sink);
         modrm_sib_disp32(out_reg0, sink);
         sib_noindex(base, sink);
         sink.put4(in_stk0.offset as u32);
         ''')
 
 # Regfill with RSP-relative 32-bit displacement.
 regfill32 = TailRecipe(
-        'regfill32', RegFill, base_size=6, ins=StackGPR32, outs=(),
+        'regfill32', RegFill, size=6, ins=StackGPR32, outs=(),
         clobbers_flags=False,
         emit='''
         let src = StackRef::sp(src, &func.stack_slots);
         let base = stk_base(src.base);
         PUT_OP(bits, rex2(base, dst), sink);
         modrm_sib_disp32(dst, sink);
         sib_noindex(base, sink);
         sink.put4(src.offset as u32);
         ''')
 
 # Like regfill32, but targeting an FPR rather than a GPR.
 fregfill32 = TailRecipe(
-        'fregfill32', RegFill, base_size=6, ins=StackFPR32, outs=(),
+        'fregfill32', RegFill, size=6, ins=StackFPR32, outs=(),
         clobbers_flags=False,
         emit='''
         let src = StackRef::sp(src, &func.stack_slots);
         let base = stk_base(src.base);
         PUT_OP(bits, rex2(base, dst), sink);
         modrm_sib_disp32(dst, sink);
         sib_noindex(base, sink);
         sink.put4(src.offset as u32);
         ''')
 
 #
 # Call/return
 #
 call_id = TailRecipe(
-        'call_id', Call, base_size=4, ins=(), outs=(),
+        'call_id', Call, size=4, ins=(), outs=(),
         emit='''
         sink.trap(TrapCode::StackOverflow, func.srclocs[inst]);
         PUT_OP(bits, BASE_REX, sink);
         // The addend adjusts for the difference between the end of the
         // instruction and the beginning of the immediate field.
         sink.reloc_external(Reloc::X86CallPCRel4,
                             &func.dfg.ext_funcs[func_ref].name,
                             -4);
         sink.put4(0);
         ''')
 
 call_plt_id = TailRecipe(
-        'call_plt_id', Call, base_size=4, ins=(), outs=(),
+        'call_plt_id', Call, size=4, ins=(), outs=(),
         emit='''
         sink.trap(TrapCode::StackOverflow, func.srclocs[inst]);
         PUT_OP(bits, BASE_REX, sink);
         sink.reloc_external(Reloc::X86CallPLTRel4,
                             &func.dfg.ext_funcs[func_ref].name,
                             -4);
         sink.put4(0);
         ''')
 
 call_r = TailRecipe(
-        'call_r', CallIndirect, base_size=1, ins=GPR, outs=(),
+        'call_r', CallIndirect, size=1, ins=GPR, outs=(),
         emit='''
         sink.trap(TrapCode::StackOverflow, func.srclocs[inst]);
         PUT_OP(bits, rex1(in_reg0), sink);
         modrm_r_bits(in_reg0, bits, sink);
         ''')
 
 ret = TailRecipe(
-        'ret', MultiAry, base_size=0, ins=(), outs=(),
+        'ret', MultiAry, size=0, ins=(), outs=(),
         emit='''
         PUT_OP(bits, BASE_REX, sink);
         ''')
 
 #
 # Branches
 #
 jmpb = TailRecipe(
-        'jmpb', Jump, base_size=1, ins=(), outs=(),
+        'jmpb', Jump, size=1, ins=(), outs=(),
         branch_range=8,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits, BASE_REX, sink);
         disp1(destination, func, sink);
         ''')
 
 jmpd = TailRecipe(
-        'jmpd', Jump, base_size=4, ins=(), outs=(),
+        'jmpd', Jump, size=4, ins=(), outs=(),
         branch_range=32,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits, BASE_REX, sink);
         disp4(destination, func, sink);
         ''')
 
 brib = TailRecipe(
-        'brib', BranchInt, base_size=1, ins=FLAG.rflags, outs=(),
+        'brib', BranchInt, size=1, ins=FLAG.rflags, outs=(),
         branch_range=8,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits | icc2opc(cond), BASE_REX, sink);
         disp1(destination, func, sink);
         ''')
 
 brid = TailRecipe(
-        'brid', BranchInt, base_size=4, ins=FLAG.rflags, outs=(),
+        'brid', BranchInt, size=4, ins=FLAG.rflags, outs=(),
         branch_range=32,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits | icc2opc(cond), BASE_REX, sink);
         disp4(destination, func, sink);
         ''')
 
 brfb = TailRecipe(
-        'brfb', BranchFloat, base_size=1, ins=FLAG.rflags, outs=(),
+        'brfb', BranchFloat, size=1, ins=FLAG.rflags, outs=(),
         branch_range=8,
         clobbers_flags=False,
         instp=floatccs(BranchFloat),
         emit='''
         PUT_OP(bits | fcc2opc(cond), BASE_REX, sink);
         disp1(destination, func, sink);
         ''')
 
 brfd = TailRecipe(
-        'brfd', BranchFloat, base_size=4, ins=FLAG.rflags, outs=(),
+        'brfd', BranchFloat, size=4, ins=FLAG.rflags, outs=(),
         branch_range=32,
         clobbers_flags=False,
         instp=floatccs(BranchFloat),
         emit='''
         PUT_OP(bits | fcc2opc(cond), BASE_REX, sink);
         disp4(destination, func, sink);
         ''')
 
-indirect_jmp = TailRecipe(
-        'indirect_jmp', IndirectJump, base_size=1, ins=GPR, outs=(),
-        clobbers_flags=False,
-        emit='''
-        PUT_OP(bits, rex1(in_reg0), sink);
-        modrm_r_bits(in_reg0, bits, sink);
-        ''')
-
-jt_entry = TailRecipe(
-        'jt_entry', BranchTableEntry, base_size=2,
-        ins=(GPR, GPR),
-        outs=(GPR),
-        clobbers_flags=False,
-        instp=valid_scale(BranchTableEntry),
-        compute_size="size_plus_maybe_offset_for_in_reg_1",
-        emit='''
-        PUT_OP(bits, rex3(in_reg1, out_reg0, in_reg0), sink);
-        if needs_offset(in_reg1) {
-            modrm_sib_disp8(out_reg0, sink);
-            sib(imm.trailing_zeros() as u8, in_reg0, in_reg1, sink);
-            sink.put1(0);
-        } else {
-            modrm_sib(out_reg0, sink);
-            sib(imm.trailing_zeros() as u8, in_reg0, in_reg1, sink);
-        }
-        ''')
-
-jt_base = TailRecipe(
-        'jt_base', BranchTableBase, base_size=5, ins=(), outs=(GPR),
-        clobbers_flags=False,
-        emit='''
-        PUT_OP(bits, rex2(0, out_reg0), sink);
-        modrm_riprel(out_reg0, sink);
-
-        // No reloc is needed here as the jump table is emitted directly after
-        // the function body.
-        jt_disp4(table, func, sink);
-        ''')
-
 #
 # Test flags and set a register.
 #
 # These setCC instructions only set the low 8 bits, and they can only write
 # ABCD registers without a REX prefix.
 #
 # Other instruction encodings accepting `b1` inputs have the same constraints
 # and only look at the low 8 bits of the input register.
 #
 
 seti = TailRecipe(
-        'seti', IntCond, base_size=1, ins=FLAG.rflags, outs=GPR,
+        'seti', IntCond, size=1, ins=FLAG.rflags, outs=GPR,
         requires_prefix=True,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits | icc2opc(cond), rex1(out_reg0), sink);
         modrm_r_bits(out_reg0, bits, sink);
         ''')
 seti_abcd = TailRecipe(
-        'seti_abcd', IntCond, base_size=1, ins=FLAG.rflags, outs=ABCD,
+        'seti_abcd', IntCond, size=1, ins=FLAG.rflags, outs=ABCD,
         when_prefixed=seti,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits | icc2opc(cond), rex1(out_reg0), sink);
         modrm_r_bits(out_reg0, bits, sink);
         ''')
 
 setf = TailRecipe(
-        'setf', FloatCond, base_size=1, ins=FLAG.rflags, outs=GPR,
+        'setf', FloatCond, size=1, ins=FLAG.rflags, outs=GPR,
         requires_prefix=True,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits | fcc2opc(cond), rex1(out_reg0), sink);
         modrm_r_bits(out_reg0, bits, sink);
         ''')
 setf_abcd = TailRecipe(
-        'setf_abcd', FloatCond, base_size=1, ins=FLAG.rflags, outs=ABCD,
+        'setf_abcd', FloatCond, size=1, ins=FLAG.rflags, outs=ABCD,
         when_prefixed=setf,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits | fcc2opc(cond), rex1(out_reg0), sink);
         modrm_r_bits(out_reg0, bits, sink);
         ''')
 
 #
 # Conditional move (a.k.a integer select)
 # (maybe-REX.W) 0F 4x modrm(r,r)
 # 1 byte, modrm(r,r), is after the opcode
 #
 cmov = TailRecipe(
-        'cmov', IntSelect, base_size=1, ins=(FLAG.rflags, GPR, GPR), outs=2,
+        'cmov', IntSelect, size=1, ins=(FLAG.rflags, GPR, GPR), outs=2,
         requires_prefix=False,
         clobbers_flags=False,
         emit='''
         PUT_OP(bits | icc2opc(cond), rex2(in_reg1, in_reg2), sink);
         modrm_rr(in_reg1, in_reg2, sink);
         ''')
 
 #
 # Bit scan forwards and reverse
 #
 bsf_and_bsr = TailRecipe(
-        'bsf_and_bsr', Unary, base_size=1, ins=GPR, outs=(GPR, FLAG.rflags),
+        'bsf_and_bsr', Unary, size=1, ins=GPR, outs=(GPR, FLAG.rflags),
         requires_prefix=False,
         clobbers_flags=True,
         emit='''
         PUT_OP(bits, rex2(in_reg0, out_reg0), sink);
         modrm_rr(in_reg0, out_reg0, sink);
         ''')
 
 #
 # Compare and set flags.
 #
 
 # XX /r, MR form. Compare two GPR registers and set flags.
 rcmp = TailRecipe(
-        'rcmp', Binary, base_size=1, ins=(GPR, GPR), outs=FLAG.rflags,
+        'rcmp', Binary, size=1, ins=(GPR, GPR), outs=FLAG.rflags,
         emit='''
         PUT_OP(bits, rex2(in_reg0, in_reg1), sink);
         modrm_rr(in_reg0, in_reg1, sink);
         ''')
 
 # XX /r, RM form. Compare two FPR registers and set flags.
 fcmp = TailRecipe(
-        'fcmp', Binary, base_size=1, ins=(FPR, FPR), outs=FLAG.rflags,
+        'fcmp', Binary, size=1, ins=(FPR, FPR), outs=FLAG.rflags,
         emit='''
         PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
         modrm_rr(in_reg1, in_reg0, sink);
         ''')
 
 # XX /n, MI form with imm8.
 rcmp_ib = TailRecipe(
-        'rcmp_ib', BinaryImm, base_size=2, ins=GPR, outs=FLAG.rflags,
+        'rcmp_ib', BinaryImm, size=2, ins=GPR, outs=FLAG.rflags,
         instp=IsSignedInt(BinaryImm.imm, 8),
         emit='''
         PUT_OP(bits, rex1(in_reg0), sink);
         modrm_r_bits(in_reg0, bits, sink);
         let imm: i64 = imm.into();
         sink.put1(imm as u8);
         ''')
 
 # XX /n, MI form with imm32.
 rcmp_id = TailRecipe(
-        'rcmp_id', BinaryImm, base_size=5, ins=GPR, outs=FLAG.rflags,
+        'rcmp_id', BinaryImm, size=5, ins=GPR, outs=FLAG.rflags,
         instp=IsSignedInt(BinaryImm.imm, 32),
         emit='''
         PUT_OP(bits, rex1(in_reg0), sink);
         modrm_r_bits(in_reg0, bits, sink);
         let imm: i64 = imm.into();
         sink.put4(imm as u32);
         ''')
 
 # Same as rcmp, but second operand is the stack pointer.
 rcmp_sp = TailRecipe(
-        'rcmp_sp', Unary, base_size=1, ins=GPR, outs=FLAG.rflags,
+        'rcmp_sp', Unary, size=1, ins=GPR, outs=FLAG.rflags,
         emit='''
         PUT_OP(bits, rex2(in_reg0, RU::rsp.into()), sink);
         modrm_rr(in_reg0, RU::rsp.into(), sink);
         ''')
 
 # Test-and-branch.
 #
 # This recipe represents the macro fusion of a test and a conditional branch.
@@ -1763,84 +1602,84 @@ rcmp_sp = TailRecipe(
 #    macro fusion is guaranteed to be possible.
 # 2. Hide the status flags from Cranelift which doesn't currently model flags.
 #
 # The encoding bits affect both the test and the branch instruction:
 #
 # Bits 0-7 are the Jcc opcode.
 # Bits 8-15 control the test instruction which always has opcode byte 0x85.
 tjccb = TailRecipe(
-        'tjccb', Branch, base_size=1 + 2, ins=GPR, outs=(),
+        'tjccb', Branch, size=1 + 2, ins=GPR, outs=(),
         branch_range=8,
         emit='''
         // test r, r.
         PUT_OP((bits & 0xff00) | 0x85, rex2(in_reg0, in_reg0), sink);
         modrm_rr(in_reg0, in_reg0, sink);
         // Jcc instruction.
         sink.put1(bits as u8);
         disp1(destination, func, sink);
         ''')
 
 tjccd = TailRecipe(
-        'tjccd', Branch, base_size=1 + 6, ins=GPR, outs=(),
+        'tjccd', Branch, size=1 + 6, ins=GPR, outs=(),
         branch_range=32,
         emit='''
         // test r, r.
         PUT_OP((bits & 0xff00) | 0x85, rex2(in_reg0, in_reg0), sink);
         modrm_rr(in_reg0, in_reg0, sink);
         // Jcc instruction.
         sink.put1(0x0f);
         sink.put1(bits as u8);
         disp4(destination, func, sink);
         ''')
 
 # 8-bit test-and-branch.
 #
 # Same as tjccb, but only looks at the low 8 bits of the register, for b1
 # types.
 t8jccb = TailRecipe(
-        't8jccb', Branch, base_size=1 + 2, ins=GPR, outs=(),
+        't8jccb', Branch, size=1 + 2, ins=GPR, outs=(),
         branch_range=8,
         requires_prefix=True,
         emit='''
         // test8 r, r.
         PUT_OP((bits & 0xff00) | 0x84, rex2(in_reg0, in_reg0), sink);
         modrm_rr(in_reg0, in_reg0, sink);
         // Jcc instruction.
         sink.put1(bits as u8);
         disp1(destination, func, sink);
         ''')
 t8jccb_abcd = TailRecipe(
-        't8jccb_abcd', Branch, base_size=1 + 2, ins=ABCD, outs=(),
+        't8jccb_abcd', Branch, size=1 + 2, ins=ABCD, outs=(),
         branch_range=8,
         when_prefixed=t8jccb,
         emit='''
         // test8 r, r.
         PUT_OP((bits & 0xff00) | 0x84, rex2(in_reg0, in_reg0), sink);
         modrm_rr(in_reg0, in_reg0, sink);
         // Jcc instruction.
         sink.put1(bits as u8);
         disp1(destination, func, sink);
         ''')
 
 t8jccd = TailRecipe(
-        't8jccd', Branch, base_size=1 + 6, ins=GPR, outs=(),
+        't8jccd', Branch, size=1 + 6, ins=GPR, outs=(),
         branch_range=32,
         requires_prefix=True,
         emit='''
         // test8 r, r.
         PUT_OP((bits & 0xff00) | 0x84, rex2(in_reg0, in_reg0), sink);
         modrm_rr(in_reg0, in_reg0, sink);
         // Jcc instruction.
         sink.put1(0x0f);
         sink.put1(bits as u8);
         disp4(destination, func, sink);
         ''')
 t8jccd_abcd = TailRecipe(
-        't8jccd_abcd', Branch, base_size=1 + 6, ins=ABCD, outs=(),
+        't8jccd_abcd', Branch, size=1 + 6, ins=ABCD, outs=(),
         branch_range=32,
         when_prefixed=t8jccd,
         emit='''
         // test8 r, r.
         PUT_OP((bits & 0xff00) | 0x84, rex2(in_reg0, in_reg0), sink);
         modrm_rr(in_reg0, in_reg0, sink);
         // Jcc instruction.
         sink.put1(0x0f);
@@ -1849,17 +1688,17 @@ t8jccd_abcd = TailRecipe(
         ''')
 
 # Worst case test-and-branch recipe for brz.b1 and brnz.b1 in 32-bit mode.
 # The register allocator can't handle a branch instruction with constrained
 # operands like the t8jccd_abcd above. This variant can accept the b1 opernd in
 # any register, but is is larger because it uses a 32-bit test instruction with
 # a 0xff immediate.
 t8jccd_long = TailRecipe(
-        't8jccd_long', Branch, base_size=5 + 6, ins=GPR, outs=(),
+        't8jccd_long', Branch, size=5 + 6, ins=GPR, outs=(),
         branch_range=32,
         emit='''
         // test32 r, 0xff.
         PUT_OP((bits & 0xff00) | 0xf7, rex1(in_reg0), sink);
         modrm_r_bits(in_reg0, bits, sink);
         sink.put4(0xff);
         // Jcc instruction.
         sink.put1(0x0f);
@@ -1880,17 +1719,17 @@ t8jccd_long = TailRecipe(
 # Since the `setCC` instructions only write an 8-bit register, we use that as
 # our `b1` representation: A `b1` value is represented as a GPR where the low 8
 # bits are known to be 0 or 1. The high bits are undefined.
 #
 # This bandaid macro doesn't support a REX prefix for the final `setCC`
 # instruction, so it is limited to the `ABCD` register class for booleans.
 # The omission of a `when_prefixed` alternative is deliberate here.
 icscc = TailRecipe(
-        'icscc', IntCompare, base_size=1 + 3, ins=(GPR, GPR), outs=ABCD,
+        'icscc', IntCompare, size=1 + 3, ins=(GPR, GPR), outs=ABCD,
         emit='''
         // Comparison instruction.
         PUT_OP(bits, rex2(in_reg0, in_reg1), sink);
         modrm_rr(in_reg0, in_reg1, sink);
         // `setCC` instruction, no REX.
         use ir::condcodes::IntCC::*;
         let setcc = match cond {
             Equal => 0x94,
@@ -1905,17 +1744,17 @@ icscc = TailRecipe(
             UnsignedLessThanOrEqual => 0x96,
         };
         sink.put1(0x0f);
         sink.put1(setcc);
         modrm_rr(out_reg0, 0, sink);
         ''')
 
 icscc_ib = TailRecipe(
-        'icscc_ib', IntCompareImm, base_size=2 + 3, ins=GPR, outs=ABCD,
+        'icscc_ib', IntCompareImm, size=2 + 3, ins=GPR, outs=ABCD,
         instp=IsSignedInt(IntCompareImm.imm, 8),
         emit='''
         // Comparison instruction.
         PUT_OP(bits, rex1(in_reg0), sink);
         modrm_r_bits(in_reg0, bits, sink);
         let imm: i64 = imm.into();
         sink.put1(imm as u8);
         // `setCC` instruction, no REX.
@@ -1933,17 +1772,17 @@ icscc_ib = TailRecipe(
             UnsignedLessThanOrEqual => 0x96,
         };
         sink.put1(0x0f);
         sink.put1(setcc);
         modrm_rr(out_reg0, 0, sink);
         ''')
 
 icscc_id = TailRecipe(
-        'icscc_id', IntCompareImm, base_size=5 + 3, ins=GPR, outs=ABCD,
+        'icscc_id', IntCompareImm, size=5 + 3, ins=GPR, outs=ABCD,
         instp=IsSignedInt(IntCompareImm.imm, 32),
         emit='''
         // Comparison instruction.
         PUT_OP(bits, rex1(in_reg0), sink);
         modrm_r_bits(in_reg0, bits, sink);
         let imm: i64 = imm.into();
         sink.put4(imm as u32);
         // `setCC` instruction, no REX.
@@ -1975,17 +1814,17 @@ icscc_id = TailRecipe(
 # UN 111 000
 # GT 000 000
 # LT 001 000
 # EQ 100 000
 #
 # Not all floating point condition codes are supported.
 # The omission of a `when_prefixed` alternative is deliberate here.
 fcscc = TailRecipe(
-        'fcscc', FloatCompare, base_size=1 + 3, ins=(FPR, FPR), outs=ABCD,
+        'fcscc', FloatCompare, size=1 + 3, ins=(FPR, FPR), outs=ABCD,
         instp=floatccs(FloatCompare),
         emit='''
         // Comparison instruction.
         PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
         modrm_rr(in_reg1, in_reg0, sink);
         // `setCC` instruction, no REX.
         use ir::condcodes::FloatCC::*;
         let setcc = match cond {
--- a/third_party/rust/cranelift-codegen/meta-python/isa/x86/registers.py
+++ b/third_party/rust/cranelift-codegen/meta-python/isa/x86/registers.py
@@ -41,17 +41,24 @@ FloatRegs = RegBank(
 FlagRegs = RegBank(
         'FlagRegs', ISA,
         'Flag registers',
         units=1,
         pressure_tracking=False,
         names=['rflags'])
 
 GPR = RegClass(IntRegs)
+# Certain types of deref encodings cannot be used with all registers.
+#   R13/RBP cannot be used with zero-offset load or store instructions.
+#   R12 cannot be used with a non-SIB-byte encoding of all derefs.
+GPR_DEREF_SAFE = GPR.without(GPR.rsp, GPR.r12)
+GPR_ZERO_DEREF_SAFE = GPR_DEREF_SAFE.without(GPR.rbp, GPR.r13)
 GPR8 = GPR[0:8]
+GPR8_DEREF_SAFE = GPR8.without(GPR.rsp)
+GPR8_ZERO_DEREF_SAFE = GPR8_DEREF_SAFE.without(GPR.rbp)
 ABCD = GPR[0:4]
 FPR = RegClass(FloatRegs)
 FPR8 = FPR[0:8]
 FLAG = RegClass(FlagRegs)
 
 # Constraints for stack operands.
 
 # Stack operand with a 32-bit signed displacement from either RBP or RSP.
--- a/third_party/rust/cranelift-codegen/meta-python/semantics/__init__.py
+++ b/third_party/rust/cranelift-codegen/meta-python/semantics/__init__.py
@@ -14,21 +14,21 @@ except ImportError:
 
 
 def verify_semantics(inst, src, xforms):
     # type: (Instruction, Rtl, InstructionSemantics) -> None
     """
     Verify that the semantics transforms in xforms correctly describe the
     instruction described by the src Rtl. This involves checking that:
         0) src is a single instance of inst
-        1) For all x \\in xforms x.src is a single instance of inst
+        1) For all x\in xforms x.src is a single instance of inst
         2) For any concrete values V of Literals in inst:
             For all concrete typing T of inst:
-                Exists single x \\in xforms that applies to src conretazied to
-                V and T
+                Exists single x \in xforms that applies to src conretazied to V
+                and T
     """
     # 0) The source rtl is always a single instance of inst
     assert len(src.rtl) == 1 and src.rtl[0].expr.inst == inst
 
     # 1) For all XForms x, x.src is a single instance of inst
     for x in xforms:
         assert len(x.src.rtl) == 1 and x.src.rtl[0].expr.inst == inst
 
--- a/third_party/rust/cranelift-codegen/src/binemit/memorysink.rs
+++ b/third_party/rust/cranelift-codegen/src/binemit/memorysink.rs
@@ -27,32 +27,33 @@ use std::ptr::write_unaligned;
 ///
 /// Any relocations in the function are forwarded to the `RelocSink` trait object.
 ///
 /// Note that `MemoryCodeSink` writes multi-byte values in the native byte order of the host. This
 /// is not the right thing to do for cross compilation.
 pub struct MemoryCodeSink<'a> {
     data: *mut u8,
     offset: isize,
-    /// Size of the machine code portion of output
-    pub code_size: isize,
     relocs: &'a mut RelocSink,
     traps: &'a mut TrapSink,
 }
 
 impl<'a> MemoryCodeSink<'a> {
     /// Create a new memory code sink that writes a function to the memory pointed to by `data`.
     ///
     /// This function is unsafe since `MemoryCodeSink` does not perform bounds checking on the
     /// memory buffer, and it can't guarantee that the `data` pointer is valid.
-    pub unsafe fn new(data: *mut u8, relocs: &'a mut RelocSink, traps: &'a mut TrapSink) -> Self {
-        Self {
+    pub unsafe fn new<'sink>(
+        data: *mut u8,
+        relocs: &'sink mut RelocSink,
+        traps: &'sink mut TrapSink,
+    ) -> MemoryCodeSink<'sink> {
+        MemoryCodeSink {
             data,
             offset: 0,
-            code_size: 0,
             relocs,
             traps,
         }
     }
 }
 
 /// A trait for receiving relocations for code that is emitted directly into memory.
 pub trait RelocSink {
@@ -125,20 +126,16 @@ impl<'a> CodeSink for MemoryCodeSink<'a>
         let ofs = self.offset();
         self.relocs.reloc_jt(ofs, rel, jt);
     }
 
     fn trap(&mut self, code: TrapCode, srcloc: SourceLoc) {
         let ofs = self.offset();
         self.traps.trap(ofs, srcloc, code);
     }
-
-    fn begin_rodata(&mut self) {
-        self.code_size = self.offset;
-    }
 }
 
 /// A `TrapSink` implementation that does nothing, which is convenient when
 /// compiling code that does not rely on trapping semantics.
 pub struct NullTrapSink {}
 
 impl TrapSink for NullTrapSink {
     fn trap(&mut self, _offset: CodeOffset, _srcloc: SourceLoc, _code: TrapCode) {}
--- a/third_party/rust/cranelift-codegen/src/binemit/mod.rs
+++ b/third_party/rust/cranelift-codegen/src/binemit/mod.rs
@@ -89,19 +89,16 @@ pub trait CodeSink {
     /// Add a relocation referencing an external symbol plus the addend at the current offset.
     fn reloc_external(&mut self, Reloc, &ExternalName, Addend);
 
     /// Add a relocation referencing a jump table.
     fn reloc_jt(&mut self, Reloc, JumpTable);
 
     /// Add trap information for the current offset.
     fn trap(&mut self, TrapCode, SourceLoc);
-
-    /// Code output is complete, read-only data may follow.
-    fn begin_rodata(&mut self);
 }
 
 /// Report a bad encoding error.
 #[cold]
 pub fn bad_encoding(func: &Function, inst: Inst) -> ! {
     panic!(
         "Bad encoding {} for {}",
         func.encodings[inst],
@@ -121,20 +118,9 @@ where
     let mut divert = RegDiversions::new();
     for ebb in func.layout.ebbs() {
         divert.clear();
         debug_assert_eq!(func.offsets[ebb], sink.offset());
         for inst in func.layout.ebb_insts(ebb) {
             emit_inst(func, inst, &mut divert, sink);
         }
     }
-
-    sink.begin_rodata();
-
-    // output jump tables
-    for (jt, jt_data) in func.jump_tables.iter() {
-        let jt_offset = func.jt_offsets[jt];
-        for ebb in jt_data.iter() {
-            let rel_offset: i32 = func.offsets[*ebb] as i32 - jt_offset as i32;
-            sink.put4(rel_offset as u32)
-        }
-    }
 }
--- a/third_party/rust/cranelift-codegen/src/binemit/relaxation.rs
+++ b/third_party/rust/cranelift-codegen/src/binemit/relaxation.rs
@@ -27,17 +27,16 @@
 //! ebb23:
 //! ```
 
 use binemit::CodeOffset;
 use cursor::{Cursor, FuncCursor};
 use ir::{Function, InstructionData, Opcode};
 use isa::{EncInfo, TargetIsa};
 use iterators::IteratorExtras;
-use regalloc::RegDiversions;
 use timing;
 use CodegenResult;
 
 /// Relax branches and compute the final layout of EBB headers in `func`.
 ///
 /// Fill in the `func.offsets` table so the function is ready for binary emission.
 pub fn relax_branches(func: &mut Function, isa: &TargetIsa) -> CodegenResult<CodeOffset> {
     let _tt = timing::relax_branches();
@@ -47,72 +46,60 @@ pub fn relax_branches(func: &mut Functio
     // Clear all offsets so we can recognize EBBs that haven't been visited yet.
     func.offsets.clear();
     func.offsets.resize(func.dfg.num_ebbs());
 
     // Start by inserting fall through instructions.
     fallthroughs(func);
 
     let mut offset = 0;
-    let mut divert = RegDiversions::new();
 
     // The relaxation algorithm iterates to convergence.
     let mut go_again = true;
     while go_again {
         go_again = false;
         offset = 0;
 
         // Visit all instructions in layout order
         let mut cur = FuncCursor::new(func);
         while let Some(ebb) = cur.next_ebb() {
-            divert.clear();
-
             // Record the offset for `ebb` and make sure we iterate until offsets are stable.
             if cur.func.offsets[ebb] != offset {
                 debug_assert!(
                     cur.func.offsets[ebb] < offset,
                     "Code shrinking during relaxation"
                 );
                 cur.func.offsets[ebb] = offset;
                 go_again = true;
             }
 
             while let Some(inst) = cur.next_inst() {
-                divert.apply(&cur.func.dfg[inst]);
-
                 let enc = cur.func.encodings[inst];
+                let size = encinfo.bytes(enc);
 
                 // See if this might be a branch that is out of range.
                 if let Some(range) = encinfo.branch_range(enc) {
                     if let Some(dest) = cur.func.dfg[inst].branch_destination() {
                         let dest_offset = cur.func.offsets[dest];
                         // This could be an out-of-range branch.
                         // Relax it unless the destination offset has not been computed yet.
                         if !range.contains(offset, dest_offset)
                             && (dest_offset != 0 || Some(dest) == cur.func.layout.entry_block())
                         {
-                            offset +=
-                                relax_branch(&mut cur, &divert, offset, dest_offset, &encinfo, isa);
+                            offset += relax_branch(&mut cur, offset, dest_offset, &encinfo, isa);
                             continue;
                         }
                     }
                 }
 
-                offset += encinfo.byte_size(enc, inst, &divert, &cur.func);
+                offset += size;
             }
         }
     }
 
-    for (jt, jt_data) in func.jump_tables.iter() {
-        func.jt_offsets[jt] = offset;
-        // TODO: this should be computed based on the min size needed to hold
-        //        the furthest branch.
-        offset += jt_data.len() as u32 * 4;
-    }
-
     Ok(offset)
 }
 
 /// Convert `jump` instructions to `fallthrough` instructions where possible and verify that any
 /// existing `fallthrough` instructions are correct.
 fn fallthroughs(func: &mut Function) {
     for (ebb, succ) in func.layout.ebbs().adjacent_pairs() {
         let term = func.layout.last_inst(ebb).expect("EBB has no terminator.");
@@ -142,17 +129,16 @@ fn fallthroughs(func: &mut Function) {
 }
 
 /// Relax the branch instruction at `cur` so it can cover the range `offset - dest_offset`.
 ///
 /// Return the size of the replacement instructions up to and including the location where `cur` is
 /// left.
 fn relax_branch(
     cur: &mut FuncCursor,
-    divert: &RegDiversions,
     offset: CodeOffset,
     dest_offset: CodeOffset,
     encinfo: &EncInfo,
     isa: &TargetIsa,
 ) -> CodeOffset {
     let inst = cur.current_inst().unwrap();
     debug!(
         "Relaxing [{}] {} for {:#x}-{:#x} range",
@@ -183,17 +169,17 @@ fn relax_branch(
                 debug!("  trying [{}]: constraints differ", encinfo.display(enc));
                 false
             } else {
                 debug!("  trying [{}]: OK", encinfo.display(enc));
                 true
             }
         }) {
         cur.func.encodings[inst] = enc;
-        return encinfo.byte_size(enc, inst, &divert, &cur.func);
+        return encinfo.bytes(enc);
     }
 
     // Note: On some RISC ISAs, conditional branches have shorter range than unconditional
     // branches, so one way of extending the range of a conditional branch is to invert its
     // condition and make it branch over an unconditional jump which has the larger range.
     //
     // Splitting the EBB is problematic this late because there may be register diversions in
     // effect across the conditional branch, and they can't survive the control flow edge to a new
--- a/third_party/rust/cranelift-codegen/src/binemit/shrink.rs
+++ b/third_party/rust/cranelift-codegen/src/binemit/shrink.rs
@@ -43,27 +43,27 @@ pub fn shrink_instructions(func: &mut Fu
                 }
 
                 let ctrl_type = func.dfg.ctrl_typevar(inst);
 
                 // Pick the last encoding with constraints that are satisfied.
                 let best_enc = isa
                     .legal_encodings(func, &func.dfg[inst], ctrl_type)
                     .filter(|e| encinfo.constraints[e.recipe()].satisfied(inst, &divert, &func))
-                    .min_by_key(|e| encinfo.byte_size(*e, inst, &divert, &func))
+                    .min_by_key(|e| encinfo.bytes(*e))
                     .unwrap();
 
                 if best_enc != enc {
                     func.encodings[inst] = best_enc;
 
                     debug!(
                         "Shrunk [{}] to [{}] in {}, reducing the size from {} to {}",
                         encinfo.display(enc),
                         encinfo.display(best_enc),
                         func.dfg.display_inst(inst, isa),
-                        encinfo.byte_size(enc, inst, &divert, &func),
-                        encinfo.byte_size(best_enc, inst, &divert, &func)
+                        encinfo.bytes(enc),
+                        encinfo.bytes(best_enc)
                     );
                 }
             }
         }
     }
 }
--- a/third_party/rust/cranelift-codegen/src/cfg_printer.rs
+++ b/third_party/rust/cranelift-codegen/src/cfg_printer.rs
@@ -10,18 +10,18 @@ use ir::Function;
 pub struct CFGPrinter<'a> {
     func: &'a Function,
     cfg: ControlFlowGraph,
 }
 
 /// A utility for pretty-printing the CFG of a `Function`.
 impl<'a> CFGPrinter<'a> {
     /// Create a new CFGPrinter.
-    pub fn new(func: &'a Function) -> Self {
-        Self {
+    pub fn new(func: &'a Function) -> CFGPrinter<'a> {
+        CFGPrinter {
             func,
             cfg: ControlFlowGraph::with_function(func),
         }
     }
 
     /// Write the CFG for this function to `w`.
     pub fn write(&self, w: &mut Write) -> Result {
         self.header(w)?;
@@ -43,21 +43,18 @@ impl<'a> CFGPrinter<'a> {
             write!(w, "    {} [shape=record, label=\"{{{}", ebb, ebb)?;
             // Add all outgoing branch instructions to the label.
             for inst in self.func.layout.ebb_insts(ebb) {
                 let idata = &self.func.dfg[inst];
                 match idata.analyze_branch(&self.func.dfg.value_lists) {
                     BranchInfo::SingleDest(dest, _) => {
                         write!(w, " | <{}>{} {}", inst, idata.opcode(), dest)?
                     }
-                    BranchInfo::Table(table, dest) => {
-                        write!(w, " | <{}>{} {}", inst, idata.opcode(), table)?;
-                        if let Some(dest) = dest {
-                            write!(w, " {}", dest)?
-                        }
+                    BranchInfo::Table(table) => {
+                        write!(w, " | <{}>{} {}", inst, idata.opcode(), table)?
                     }
                     BranchInfo::NotABranch => {}
                 }
             }
             writeln!(w, "}}\"]")?
         }
         Ok(())
     }
--- a/third_party/rust/cranelift-codegen/src/context.rs
+++ b/third_party/rust/cranelift-codegen/src/context.rs
@@ -17,21 +17,21 @@ use dominator_tree::DominatorTree;
 use flowgraph::ControlFlowGraph;
 use ir::Function;
 use isa::TargetIsa;
 use legalize_function;
 use licm::do_licm;
 use loop_analysis::LoopAnalysis;
 use nan_canonicalization::do_nan_canonicalization;
 use postopt::do_postopt;
+use preopt::do_preopt;
 use regalloc;
 use result::CodegenResult;
 use settings::{FlagsOrIsa, OptLevel};
 use simple_gvn::do_simple_gvn;
-use simple_preopt::do_preopt;
 use std::vec::Vec;
 use timing;
 use unreachable_code::eliminate_unreachable_code;
 use verifier::{verify_context, verify_locations, VerifierErrors, VerifierResult};
 
 /// Persistent data structures and compilation pipeline.
 pub struct Context {
     /// The function we're compiling.
@@ -96,17 +96,24 @@ impl Context {
         isa: &TargetIsa,
         mem: &mut Vec<u8>,
         relocs: &mut RelocSink,
         traps: &mut TrapSink,
     ) -> CodegenResult<()> {
         let code_size = self.compile(isa)?;
         let old_len = mem.len();
         mem.resize(old_len + code_size as usize, 0);
-        unsafe { self.emit_to_memory(isa, mem.as_mut_ptr().add(old_len), relocs, traps) };
+        unsafe {
+            self.emit_to_memory(
+                isa,
+                mem.as_mut_ptr().offset(old_len as isize),
+                relocs,
+                traps,
+            )
+        };
         Ok(())
     }
 
     /// Compile the function.
     ///
     /// Run the function through all the passes necessary to generate code for the target ISA
     /// represented by `isa`. This does not include the final step of emitting machine code into a
     /// code sink.
@@ -316,11 +323,12 @@ impl Context {
         Ok(())
     }
 
     /// Run the branch relaxation pass and return the final code size.
     pub fn relax_branches(&mut self, isa: &TargetIsa) -> CodegenResult<CodeOffset> {
         let code_size = relax_branches(&mut self.func, isa)?;
         self.verify_if(isa)?;
         self.verify_locations_if(isa)?;
+
         Ok(code_size)
     }
 }
--- a/third_party/rust/cranelift-codegen/src/cursor.rs
+++ b/third_party/rust/cranelift-codegen/src/cursor.rs
@@ -575,18 +575,18 @@ pub struct FuncCursor<'f> {
     srcloc: ir::SourceLoc,
 
     /// The referenced function.
     pub func: &'f mut ir::Function,
 }
 
 impl<'f> FuncCursor<'f> {
     /// Create a new `FuncCursor` pointing nowhere.
-    pub fn new(func: &'f mut ir::Function) -> Self {
-        Self {
+    pub fn new(func: &'f mut ir::Function) -> FuncCursor<'f> {
+        FuncCursor {
             pos: CursorPosition::Nowhere,
             srcloc: Default::default(),
             func,
         }
     }
 
     /// Use the source location of `inst` for future instructions.
     pub fn use_srcloc(&mut self, inst: ir::Inst) {
@@ -657,18 +657,18 @@ pub struct EncCursor<'f> {
     pub func: &'f mut ir::Function,
 
     /// The target ISA that will be used to encode instructions.
     pub isa: &'f TargetIsa,
 }
 
 impl<'f> EncCursor<'f> {
     /// Create a new `EncCursor` pointing nowhere.
-    pub fn new(func: &'f mut ir::Function, isa: &'f TargetIsa) -> Self {
-        Self {
+    pub fn new(func: &'f mut ir::Function, isa: &'f TargetIsa) -> EncCursor<'f> {
+        EncCursor {
             pos: CursorPosition::Nowhere,
             srcloc: Default::default(),
             built_inst: None,
             func,
             isa,
         }
     }
 
--- a/third_party/rust/cranelift-codegen/src/dominator_tree.rs
+++ b/third_party/rust/cranelift-codegen/src/dominator_tree.rs
@@ -1,11 +1,11 @@
 //! A Dominator Tree represented as mappings of Ebbs to their immediate dominator.
 
-use entity::SecondaryMap;
+use entity::EntityMap;
 use flowgraph::{BasicBlock, ControlFlowGraph};
 use ir::instructions::BranchInfo;
 use ir::{Ebb, ExpandedProgramPoint, Function, Inst, Layout, ProgramOrder, Value};
 use packed_option::PackedOption;
 use std::cmp;
 use std::cmp::Ordering;
 use std::mem;
 use std::vec::Vec;
@@ -33,17 +33,17 @@ struct DomNode {
     ///
     /// This is `None` for unreachable blocks and the entry block which doesn't have an immediate
     /// dominator.
     idom: PackedOption<Inst>,
 }
 
 /// The dominator tree for a single function.
 pub struct DominatorTree {
-    nodes: SecondaryMap<Ebb, DomNode>,
+    nodes: EntityMap<Ebb, DomNode>,
 
     /// CFG post-order of all reachable EBBs.
     postorder: Vec<Ebb>,
 
     /// Scratch memory used by `compute_postorder()`.
     stack: Vec<Ebb>,
 
     valid: bool,
@@ -212,17 +212,17 @@ impl DominatorTree {
     }
 }
 
 impl DominatorTree {
     /// Allocate a new blank dominator tree. Use `compute` to compute the dominator tree for a
     /// function.
     pub fn new() -> Self {
         Self {
-            nodes: SecondaryMap::new(),
+            nodes: EntityMap::new(),
             postorder: Vec::new(),
             stack: Vec::new(),
             valid: false,
         }
     }
 
     /// Allocate and compute a dominator tree.
     pub fn with_function(func: &Function, cfg: &ControlFlowGraph) -> Self {
@@ -340,38 +340,35 @@ impl DominatorTree {
     /// Push `ebb` successors onto `self.stack`, filtering out those that have already been seen.
     ///
     /// The successors are pushed in program order which is important to get a split-invariant
     /// post-order. Split-invariant means that if an EBB is split in two, we get the same
     /// post-order except for the insertion of the new EBB header at the split point.
     fn push_successors(&mut self, func: &Function, ebb: Ebb) {
         for inst in func.layout.ebb_insts(ebb) {
             match func.dfg.analyze_branch(inst) {
-                BranchInfo::SingleDest(succ, _) => self.push_if_unseen(succ),
-                BranchInfo::Table(jt, dest) => {
-                    for succ in func.jump_tables[jt].iter() {
-                        self.push_if_unseen(*succ);
+                BranchInfo::SingleDest(succ, _) => {
+                    if self.nodes[succ].rpo_number == 0 {
+                        self.nodes[succ].rpo_number = SEEN;
+                        self.stack.push(succ);
                     }
-                    if let Some(dest) = dest {
-                        self.push_if_unseen(dest);
+                }
+                BranchInfo::Table(jt) => {
+                    for (_, succ) in func.jump_tables[jt].entries() {
+                        if self.nodes[succ].rpo_number == 0 {
+                            self.nodes[succ].rpo_number = SEEN;
+                            self.stack.push(succ);
+                        }
                     }
                 }
                 BranchInfo::NotABranch => {}
             }
         }
     }
 
-    /// Push `ebb` onto `self.stack` if it has not already been seen.
-    fn push_if_unseen(&mut self, ebb: Ebb) {
-        if self.nodes[ebb].rpo_number == 0 {
-            self.nodes[ebb].rpo_number = SEEN;
-            self.stack.push(ebb);
-        }
-    }
-
     /// Build a dominator tree from a control flow graph using Keith D. Cooper's
     /// "Simple, Fast Dominator Algorithm."
     fn compute_domtree(&mut self, func: &Function, cfg: &ControlFlowGraph) {
         // During this algorithm, `rpo_number` has the following values:
         //
         // 0: EBB is not reachable.
         // 1: EBB is reachable, but has not yet been visited during the first pass. This is set by
         // `compute_postorder`.
@@ -503,17 +500,17 @@ impl DominatorTree {
 ///
 /// - A forward traversable dominator tree through the `children()` iterator.
 /// - An ordering of EBBs according to a dominator tree pre-order.
 /// - Constant time dominance checks at the EBB granularity.
 ///
 /// The information in this auxillary data structure is not easy to update when the control flow
 /// graph changes, which is why it is kept separate.
 pub struct DominatorTreePreorder {
-    nodes: SecondaryMap<Ebb, ExtraNode>,
+    nodes: EntityMap<Ebb, ExtraNode>,
 
     // Scratch memory used by `compute_postorder()`.
     stack: Vec<Ebb>,
 }
 
 #[derive(Default, Clone)]
 struct ExtraNode {
     /// First child node in the domtree.
@@ -531,17 +528,17 @@ struct ExtraNode {
     pre_max: u32,
 }
 
 /// Creating and computing the dominator tree pre-order.
 impl DominatorTreePreorder {
     /// Create a new blank `DominatorTreePreorder`.
     pub fn new() -> Self {
         Self {
-            nodes: SecondaryMap::new(),
+            nodes: EntityMap::new(),
             stack: Vec::new(),
         }
     }
 
     /// Recompute this data structure to match `domtree`.
     pub fn compute(&mut self, domtree: &DominatorTree, layout: &Layout) {
         self.nodes.clear();
         debug_assert_eq!(self.stack.len(), 0);
@@ -664,17 +661,17 @@ impl DominatorTreePreorder {
         let da = func.dfg.value_def(a);
         let db = func.dfg.value_def(b);
         self.pre_cmp(da, db, &func.layout)
             .then_with(|| da.num().cmp(&db.num()))
     }
 }
 
 #[cfg(test)]
-mod tests {
+mod test {
     use super::*;
     use cursor::{Cursor, FuncCursor};
     use flowgraph::ControlFlowGraph;
     use ir::types::*;
     use ir::{Function, InstBuilder, TrapCode};
     use settings;
     use verifier::{verify_context, VerifierErrors};
 
--- a/third_party/rust/cranelift-codegen/src/flowgraph.rs
+++ b/third_party/rust/cranelift-codegen/src/flowgraph.rs
@@ -19,17 +19,17 @@
 //!
 //!         jmp Ebb2     ; end of basic block
 //! ```
 //!
 //! Here `Ebb1` and `Ebb2` would each have a single predecessor denoted as `(Ebb0, brz)`
 //! and `(Ebb0, jmp Ebb2)` respectively.
 
 use bforest;
-use entity::SecondaryMap;
+use entity::EntityMap;
 use ir::instructions::BranchInfo;
 use ir::{Ebb, Function, Inst};
 use std::mem;
 use timing;
 
 /// A basic block denoted by its enclosing Ebb and last instruction.
 #[derive(PartialEq, Eq)]
 pub struct BasicBlock {
@@ -67,27 +67,27 @@ struct CFGNode {
     /// The set is ordered by EBB number, indicated by the `()` comparator type.
     pub successors: bforest::Set<Ebb>,
 }
 
 /// The Control Flow Graph maintains a mapping of ebbs to their predecessors
 /// and successors where predecessors are basic blocks and successors are
 /// extended basic blocks.
 pub struct ControlFlowGraph {
-    data: SecondaryMap<Ebb, CFGNode>,
+    data: EntityMap<Ebb, CFGNode>,
     pred_forest: bforest::MapForest<Inst, Ebb>,
     succ_forest: bforest::SetForest<Ebb>,
     valid: bool,
 }
 
 impl ControlFlowGraph {
     /// Allocate a new blank control flow graph.
     pub fn new() -> Self {
         Self {
-            data: SecondaryMap::new(),
+            data: EntityMap::new(),
             valid: false,
             pred_forest: bforest::MapForest::new(),
             succ_forest: bforest::SetForest::new(),
         }
     }
 
     /// Clear all data structures in this control flow graph.
     pub fn clear(&mut self) {
@@ -120,23 +120,20 @@ impl ControlFlowGraph {
     }
 
     fn compute_ebb(&mut self, func: &Function, ebb: Ebb) {
         for inst in func.layout.ebb_insts(ebb) {
             match func.dfg.analyze_branch(inst) {
                 BranchInfo::SingleDest(dest, _) => {
                     self.add_edge(ebb, inst, dest);
                 }
-                BranchInfo::Table(jt, dest) => {
-                    if let Some(dest) = dest {
+                BranchInfo::Table(jt) => {
+                    for (_, dest) in func.jump_tables[jt].entries() {
                         self.add_edge(ebb, inst, dest);
                     }
-                    for dest in func.jump_tables[jt].iter() {
-                        self.add_edge(ebb, inst, *dest);
-                    }
                 }
                 BranchInfo::NotABranch => {}
             }
         }
     }
 
     fn invalidate_ebb_successors(&mut self, ebb: Ebb) {
         // Temporarily take ownership because we need mutable access to self.data inside the loop.
--- a/third_party/rust/cranelift-codegen/src/ir/builder.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/builder.rs
@@ -23,17 +23,17 @@ pub trait InstBuilderBase<'f>: Sized {
     fn data_flow_graph(&self) -> &DataFlowGraph;
     /// Get a mutable reference to the data flow graph that will hold the constructed
     /// instructions.
     fn data_flow_graph_mut(&mut self) -> &mut DataFlowGraph;
 
     /// Insert an instruction and return a reference to it, consuming the builder.
     ///
     /// The result types may depend on a controlling type variable. For non-polymorphic
-    /// instructions with multiple results, pass `INVALID` for the `ctrl_typevar` argument.
+    /// instructions with multiple results, pass `VOID` for the `ctrl_typevar` argument.
     fn build(self, data: InstructionData, ctrl_typevar: Type) -> (Inst, &'f mut DataFlowGraph);
 }
 
 // Include trait code generated by `lib/codegen/meta-python/gen_instr.py`.
 //
 // This file defines the `InstBuilder` trait as an extension of `InstBuilderBase` with methods per
 // instruction format and per opcode.
 include!(concat!(env!("OUT_DIR"), "/inst_builder.rs"));
@@ -69,18 +69,18 @@ use std::marker::PhantomData;
 pub struct InsertBuilder<'f, IIB: InstInserterBase<'f>> {
     inserter: IIB,
     unused: PhantomData<&'f u32>,
 }
 
 impl<'f, IIB: InstInserterBase<'f>> InsertBuilder<'f, IIB> {
     /// Create a new builder which inserts instructions at `pos`.
     /// The `dfg` and `pos.layout` references should be from the same `Function`.
-    pub fn new(inserter: IIB) -> Self {
-        Self {
+    pub fn new(inserter: IIB) -> InsertBuilder<'f, IIB> {
+        InsertBuilder {
             inserter,
             unused: PhantomData,
         }
     }
 
     /// Reuse result values in `reuse`.
     ///
     /// Convert this builder into one that will reuse the provided result values instead of
@@ -180,18 +180,18 @@ where
 /// bug to leave result values dangling.
 pub struct ReplaceBuilder<'f> {
     dfg: &'f mut DataFlowGraph,
     inst: Inst,
 }
 
 impl<'f> ReplaceBuilder<'f> {
     /// Create a `ReplaceBuilder` that will overwrite `inst`.
-    pub fn new(dfg: &'f mut DataFlowGraph, inst: Inst) -> Self {
-        Self { dfg, inst }
+    pub fn new(dfg: &'f mut DataFlowGraph, inst: Inst) -> ReplaceBuilder {
+        ReplaceBuilder { dfg, inst }
     }
 }
 
 impl<'f> InstBuilderBase<'f> for ReplaceBuilder<'f> {
     fn data_flow_graph(&self) -> &DataFlowGraph {
         self.dfg
     }
 
--- a/third_party/rust/cranelift-codegen/src/ir/dfg.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/dfg.rs
@@ -1,11 +1,11 @@
 //! Data flow graph tracking Instructions, Values, and EBBs.
 
-use entity::{self, PrimaryMap, SecondaryMap};
+use entity::{EntityMap, PrimaryMap};
 use ir;
 use ir::builder::ReplaceBuilder;
 use ir::extfunc::ExtFuncData;
 use ir::instructions::{BranchInfo, CallInfo, InstructionData};
 use ir::types;
 use ir::{Ebb, FuncRef, Inst, SigRef, Signature, Type, Value, ValueList, ValueListPool};
 use isa::TargetIsa;
 use packed_option::ReservedValue;
@@ -29,17 +29,17 @@ pub struct DataFlowGraph {
     /// The instructions in this map are not in program order. That is tracked by `Layout`, along
     /// with the EBB containing each instruction.
     insts: PrimaryMap<Inst, InstructionData>,
 
     /// List of result values for each instruction.
     ///
     /// This map gets resized automatically by `make_inst()` so it is always in sync with the
     /// primary `insts` map.
-    results: SecondaryMap<Inst, ValueList>,
+    results: EntityMap<Inst, ValueList>,
 
     /// Extended basic blocks in the function and their parameters.
     ///
     /// This map is not in program order. That is handled by `Layout`, and so is the sequence of
     /// instructions contained in each EBB.
     ebbs: PrimaryMap<Ebb, EbbData>,
 
     /// Memory pool of value lists.
@@ -62,17 +62,17 @@ pub struct DataFlowGraph {
     pub ext_funcs: PrimaryMap<FuncRef, ExtFuncData>,
 }
 
 impl DataFlowGraph {
     /// Create a new empty `DataFlowGraph`.
     pub fn new() -> Self {
         Self {
             insts: PrimaryMap::new(),
-            results: SecondaryMap::new(),
+            results: EntityMap::new(),
             ebbs: PrimaryMap::new(),
             value_lists: ValueListPool::new(),
             values: PrimaryMap::new(),
             signatures: PrimaryMap::new(),
             ext_funcs: PrimaryMap::new(),
         }
     }
 
@@ -85,30 +85,30 @@ impl DataFlowGraph {
         self.values.clear();
         self.signatures.clear();
         self.ext_funcs.clear();
     }
 
     /// Get the total number of instructions created in this function, whether they are currently
     /// inserted in the layout or not.
     ///
-    /// This is intended for use with `SecondaryMap::with_capacity`.
+    /// This is intended for use with `EntityMap::with_capacity`.
     pub fn num_insts(&self) -> usize {
         self.insts.len()
     }
 
     /// Returns `true` if the given instruction reference is valid.
     pub fn inst_is_valid(&self, inst: Inst) -> bool {
         self.insts.is_valid(inst)
     }
 
     /// Get the total number of extended basic blocks created in this function, whether they are
     /// currently inserted in the layout or not.
     ///
-    /// This is intended for use with `SecondaryMap::with_capacity`.
+    /// This is intended for use with `EntityMap::with_capacity`.
     pub fn num_ebbs(&self) -> usize {
         self.ebbs.len()
     }
 
     /// Returns `true` if the given ebb reference is valid.
     pub fn ebb_is_valid(&self, ebb: Ebb) -> bool {
         self.ebbs.is_valid(ebb)
     }
@@ -122,17 +122,17 @@ impl DataFlowGraph {
 /// Resolve value aliases.
 ///
 /// Find the original SSA value that `value` aliases, or None if an
 /// alias cycle is detected.
 fn maybe_resolve_aliases(values: &PrimaryMap<Value, ValueData>, value: Value) -> Option<Value> {
     let mut v = value;
 
     // Note that values may be empty here.
-    for _ in 0..=values.len() {
+    for _ in 0..1 + values.len() {
         if let ValueData::Alias { original, .. } = values[v] {
             v = original;
         } else {
             return Some(v);
         }
     }
 
     None
@@ -144,62 +144,25 @@ fn maybe_resolve_aliases(values: &Primar
 fn resolve_aliases(values: &PrimaryMap<Value, ValueData>, value: Value) -> Value {
     if let Some(v) = maybe_resolve_aliases(values, value) {
         v
     } else {
         panic!("Value alias loop detected for {}", value);
     }
 }
 
-/// Iterator over all Values in a DFG
-pub struct Values<'a> {
-    inner: entity::Iter<'a, Value, ValueData>,
-}
-
-/// Check for non-values
-fn valid_valuedata(data: &ValueData) -> bool {
-    if let ValueData::Alias {
-        ty: types::INVALID,
-        original,
-    } = *data
-    {
-        if original == Value::reserved_value() {
-            return false;
-        }
-    }
-    true
-}
-
-impl<'a> Iterator for Values<'a> {
-    type Item = Value;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        self.inner
-            .by_ref()
-            .find(|kv| valid_valuedata(kv.1))
-            .map(|kv| kv.0)
-    }
-}
-
 /// Handling values.
 ///
 /// Values are either EBB parameters or instruction results.
 impl DataFlowGraph {
     /// Allocate an extended value entry.
     fn make_value(&mut self, data: ValueData) -> Value {
         self.values.push(data)
     }
 
-    /// Get an iterator over all values.
-    pub fn values<'a>(&'a self) -> Values {
-        Values {
-            inner: self.values.iter(),
-        }
-    }
-
     /// Check if a value reference is valid.
     pub fn value_is_valid(&self, v: Value) -> bool {
         self.values.is_valid(v)
     }
 
     /// Get the type of a value.
     pub fn value_type(&self, v: Value) -> Type {
         match self.values[v] {
@@ -281,17 +244,17 @@ impl DataFlowGraph {
             self.value_type(dest),
             ty,
             "Aliasing {} to {} would change its type {} to {}",
             dest,
             src,
             self.value_type(dest),
             ty
         );
-        debug_assert_ne!(ty, types::INVALID);
+        debug_assert_ne!(ty, types::VOID);
 
         self.values[dest] = ValueData::Alias { ty, original };
     }
 
     /// Replace the results of one instruction with aliases to the results of another.
     ///
     /// Change all the results of `dest_inst` to behave as aliases of
     /// corresponding results of `src_inst`, as if calling change_to_alias for
@@ -325,17 +288,17 @@ impl DataFlowGraph {
                 self.value_type(dest),
                 ty,
                 "Aliasing {} to {} would change its type {} to {}",
                 dest,
                 src,
                 self.value_type(dest),
                 ty
             );
-            debug_assert_ne!(ty, types::INVALID);
+            debug_assert_ne!(ty, types::VOID);
 
             self.values[dest] = ValueData::Alias { ty, original };
         }
 
         self.clear_results(dest_inst);
     }
 }
 
@@ -454,17 +417,17 @@ impl DataFlowGraph {
 
     /// 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
     /// provided `ctrl_typevar` type for polymorphic instructions. For non-polymorphic
-    /// instructions, `ctrl_typevar` is ignored, and `INVALID` can be used.
+    /// instructions, `ctrl_typevar` is ignored, and `VOID` can be used.
     ///
     /// The type of the first result value is also set, even if it was already set in the
     /// `InstructionData` passed to `make_inst`. If this function is called with a single-result
     /// instruction, that is the only effect.
     pub fn make_inst_results(&mut self, inst: Inst, ctrl_typevar: Type) -> usize {
         self.make_inst_results_reusing(inst, ctrl_typevar, iter::empty())
     }
 
@@ -672,22 +635,22 @@ impl DataFlowGraph {
         self.call_signature(inst).and_then(|sigref| {
             self.signatures[sigref]
                 .returns
                 .get(result_idx - fixed_results)
                 .map(|&arg| arg.value_type)