Repository: bytecodealliance/wasmtime
Pull request #7721 (2023-12-21 22:47:12)

winch: Add memory instructions
This commit adds support for the following memory instructions to winch:

* `data.drop`
* `memory.init`
* `memory.fill`
* `memory.copy`
* `memory.size`
* `memory.grow`

In general the implementation is similar to what other instructions via builtins are handled (e.g. table instructions), which involve stack manipulation prior to emitting a builtin function call, with the exception of `memory.size`, which involves loading the current length from the `VMContext` pointer.

<!--
Please make sure you include the following information:

- If this work has been discussed elsewhere, please include a link to that
  conversation. If it was discussed in an issue, just mention "issue #...".

- Explain why this change is needed. If the details are in an issue already,
  this can be brief.

Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.html

Please ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->


github-actions[bot]: #### Subscribe to Label Action

cc @fitzgen, @saulecabrera

<details>
This issue or pull request has been labeled: "fuzzing", "winch"

Thus the following users have been cc'd because of the following labels:

* fitzgen: fuzzing
* saulecabrera: winch

To subscribe or unsubscribe from this label, edit the <code>.github/subscribe-to-label.json</code> configuration file.

[Learn more.](https://github.com/bytecodealliance/subscribe-to-label-action)
</details>

Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 0380a7652..eaea2df30 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -43,6 +43,15 @@ version = "0.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b"
 
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "anes"
 version = "0.1.6"
@@ -124,17 +133,6 @@ dependencies = [
  "syn 2.0.32",
 ]
 
-[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi 0.1.19",
- "libc",
- "winapi",
-]
-
 [[package]]
 name = "autocfg"
 version = "1.1.0"
@@ -257,21 +255,21 @@ dependencies = [
 
 [[package]]
 name = "cap-fs-ext"
-version = "2.0.0"
+version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b779b2d0a001c125b4584ad586268fb4b92d957bff8d26d7fe0dd78283faa814"
+checksum = "88e341d15ac1029aadce600be764a1a1edafe40e03cde23285bc1d261b3a4866"
 dependencies = [
  "cap-primitives",
  "cap-std",
  "io-lifetimes",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
 name = "cap-net-ext"
-version = "2.0.0"
+version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ffc30dee200c20b4dcb80572226f42658e1d9c4b668656d7cc59c33d50e396e"
+checksum = "434168fe6533055f0f4204039abe3ff6d7db338ef46872a5fa39e9d5ad5ab7a9"
 dependencies = [
  "cap-primitives",
  "cap-std",
@@ -281,9 +279,9 @@ dependencies = [
 
 [[package]]
 name = "cap-primitives"
-version = "2.0.0"
+version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bf30c373a3bee22c292b1b6a7a26736a38376840f1af3d2d806455edf8c3899"
+checksum = "fe16767ed8eee6d3f1f00d6a7576b81c226ab917eb54b96e5f77a5216ef67abb"
 dependencies = [
  "ambient-authority",
  "fs-set-times",
@@ -292,15 +290,15 @@ dependencies = [
  "ipnet",
  "maybe-owned",
  "rustix",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
  "winx",
 ]
 
 [[package]]
 name = "cap-rand"
-version = "2.0.0"
+version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "577de6cff7c2a47d6b13efe5dd28bf116bd7f8f7db164ea95b7cc2640711f522"
+checksum = "20e5695565f0cd7106bc3c7170323597540e772bb73e0be2cd2c662a0f8fa4ca"
 dependencies = [
  "ambient-authority",
  "rand",
@@ -308,9 +306,9 @@ dependencies = [
 
 [[package]]
 name = "cap-std"
-version = "2.0.0"
+version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84bade423fa6403efeebeafe568fdb230e8c590a275fba2ba978dd112efcf6e9"
+checksum = "593db20e4c51f62d3284bae7ee718849c3214f93a3b94ea1899ad85ba119d330"
 dependencies = [
  "cap-primitives",
  "io-extras",
@@ -320,9 +318,9 @@ dependencies = [
 
 [[package]]
 name = "cap-tempfile"
-version = "2.0.0"
+version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b9e3348a3510c4619b4c7a7bcdef09a71221da18f266bda3ed6b9aea2c509e2"
+checksum = "29d0d2d91fc0da2e0d811289a0d3518b8aba8a122fc0014f702feb3967fbe857"
 dependencies = [
  "cap-std",
  "rand",
@@ -332,11 +330,13 @@ dependencies = [
 
 [[package]]
 name = "cap-time-ext"
-version = "2.0.0"
+version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8f52b3c8f4abfe3252fd0a071f3004aaa3b18936ec97bdbd8763ce03aff6247"
+checksum = "03261630f291f425430a36f38c847828265bc928f517cdd2004c56f4b02f002b"
 dependencies = [
+ "ambient-authority",
  "cap-primitives",
+ "iana-time-zone",
  "once_cell",
  "rustix",
  "winx",
@@ -393,11 +393,12 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
 
 [[package]]
 name = "cc"
-version = "1.0.73"
+version = "1.0.83"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
 dependencies = [
  "jobserver",
+ "libc",
 ]
 
 [[package]]
@@ -524,7 +525,7 @@ version = "0.0.0"
 dependencies = [
  "anyhow",
  "arbitrary",
- "env_logger 0.10.0",
+ "env_logger",
  "wasmtime",
 ]
 
@@ -543,6 +544,12 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
+
 [[package]]
 name = "cpp_demangle"
 version = "0.3.5"
@@ -809,7 +816,7 @@ dependencies = [
  "fxhash",
  "indicatif",
  "log",
- "pretty_env_logger 0.5.0",
+ "pretty_env_logger",
  "rayon",
  "regalloc2",
  "serde",
@@ -1038,26 +1045,13 @@ dependencies = [
  "cfg-if",
 ]
 
-[[package]]
-name = "env_logger"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
-dependencies = [
- "atty",
- "humantime 1.3.0",
- "log",
- "regex",
- "termcolor",
-]
-
 [[package]]
 name = "env_logger"
 version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
 dependencies = [
- "humantime 2.1.0",
+ "humantime",
  "is-terminal",
  "log",
  "regex",
@@ -1072,12 +1066,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
 
 [[package]]
 name = "errno"
-version = "0.3.6"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e"
+checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
 dependencies = [
  "libc",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -1106,13 +1100,13 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
 
 [[package]]
 name = "fd-lock"
-version = "4.0.0"
+version = "4.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b0377f1edc77dbd1118507bc7a66e4ab64d2b90c66f90726dc801e73a8c68f9"
+checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947"
 dependencies = [
  "cfg-if",
  "rustix",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -1121,7 +1115,7 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8a3cc21c33af89af0930c8cae4ade5e6fdc17b5d2c97b3d2e2edb67a1cf683f3"
 dependencies = [
- "env_logger 0.10.0",
+ "env_logger",
  "log",
 ]
 
@@ -1170,13 +1164,13 @@ dependencies = [
 
 [[package]]
 name = "fs-set-times"
-version = "0.20.0"
+version = "0.20.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd738b84894214045e8414eaded76359b4a5773f0a0a56b16575110739cdcf39"
+checksum = "033b337d725b97690d86893f9de22b67b80dcc4e9ad815f348254c38119db8fb"
 dependencies = [
  "io-lifetimes",
  "rustix",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -1368,15 +1362,6 @@ dependencies = [
  "unicode-segmentation",
 ]
 
-[[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
 [[package]]
 name = "hermit-abi"
 version = "0.3.0"
@@ -1429,15 +1414,6 @@ version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
 
-[[package]]
-name = "humantime"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
-dependencies = [
- "quick-error 1.2.3",
-]
-
 [[package]]
 name = "humantime"
 version = "2.1.0"
@@ -1464,6 +1440,29 @@ dependencies = [
  "want",
 ]
 
+[[package]]
+name = "iana-time-zone"
+version = "0.1.59"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
 [[package]]
 name = "id-arena"
 version = "2.2.1"
@@ -1530,12 +1529,12 @@ dependencies = [
 
 [[package]]
 name = "io-extras"
-version = "0.18.0"
+version = "0.18.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d3c230ee517ee76b1cc593b52939ff68deda3fae9e41eca426c6b4993df51c4"
+checksum = "c301e73fb90e8a29e600a9f402d095765f74310d582916a952f618836a1bd1ed"
 dependencies = [
  "io-lifetimes",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -1552,13 +1551,13 @@ checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
 
 [[package]]
 name = "is-terminal"
-version = "0.4.9"
+version = "0.4.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
+checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"
 dependencies = [
- "hermit-abi 0.3.0",
+ "hermit-abi",
  "rustix",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -1566,7 +1565,7 @@ name = "isle-fuzz"
 version = "0.0.0"
 dependencies = [
  "cranelift-isle",
- "env_logger 0.10.0",
+ "env_logger",
  "libfuzzer-sys",
  "log",
 ]
@@ -1577,7 +1576,7 @@ version = "0.0.0"
 dependencies = [
  "clap",
  "cranelift-isle",
- "env_logger 0.10.0",
+ "env_logger",
 ]
 
 [[package]]
@@ -1647,9 +1646,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
 
 [[package]]
 name = "libc"
-version = "0.2.149"
+version = "0.2.151"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
+checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
 
 [[package]]
 name = "libfuzzer-sys"
@@ -1664,12 +1663,12 @@ dependencies = [
 
 [[package]]
 name = "libloading"
-version = "0.7.3"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
+checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
 dependencies = [
  "cfg-if",
- "winapi",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -1680,9 +1679,9 @@ checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.4.10"
+version = "0.4.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"
+checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
 
 [[package]]
 name = "listenfd"
@@ -1806,7 +1805,7 @@ version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
 dependencies = [
- "hermit-abi 0.3.0",
+ "hermit-abi",
  "libc",
 ]
 
@@ -1871,9 +1870,9 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
 
 [[package]]
 name = "openvino"
-version = "0.5.0"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbc731d9a7805dd533b69de3ee33062d5ea1dfa9fca1c19f8fd165b62e2cdde7"
+checksum = "24bd3a7ef39968e6a4f1b1206c1c876f9bd50cf739ccbcd69f8539bbac5dcc7a"
 dependencies = [
  "openvino-finder",
  "openvino-sys",
@@ -1882,9 +1881,9 @@ dependencies = [
 
 [[package]]
 name = "openvino-finder"
-version = "0.5.0"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8bbd80eea06c2b9ec3dce85900ff3ae596c01105b759b38a005af69bbeb4d07"
+checksum = "05d234d1394a413ea8adaf0c40806b9ad1946be6310b441f688840654a331973"
 dependencies = [
  "cfg-if",
  "log",
@@ -1892,14 +1891,14 @@ dependencies = [
 
 [[package]]
 name = "openvino-sys"
-version = "0.5.0"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "318ed662bdf05a3f86486408159e806d53363171621a8000b81366fab5158713"
+checksum = "44c98acf37fc84ad9d7da4dc6c18f0f60ad209b43a6f555be01f9003d0a2a43d"
 dependencies = [
+ "env_logger",
  "libloading",
  "once_cell",
  "openvino-finder",
- "pretty_env_logger 0.4.0",
 ]
 
 [[package]]
@@ -1966,23 +1965,13 @@ version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
 
-[[package]]
-name = "pretty_env_logger"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
-dependencies = [
- "env_logger 0.7.1",
- "log",
-]
-
 [[package]]
 name = "pretty_env_logger"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c"
 dependencies = [
- "env_logger 0.10.0",
+ "env_logger",
  "log",
 ]
 
@@ -2234,9 +2223,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 
 [[package]]
 name = "rustix"
-version = "0.38.21"
+version = "0.38.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
+checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
 dependencies = [
  "bitflags 2.4.1",
  "errno",
@@ -2244,7 +2233,7 @@ dependencies = [
  "libc",
  "linux-raw-sys",
  "once_cell",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -2526,9 +2515,9 @@ dependencies = [
 
 [[package]]
 name = "system-interface"
-version = "0.26.0"
+version = "0.26.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27ce32341b2c0b70c144bbf35627fdc1ef18c76ced5e5e7b3ee8b5ba6b2ab6a0"
+checksum = "0682e006dd35771e392a6623ac180999a9a854b1d4a6c12fb2e804941c2b1f58"
 dependencies = [
  "bitflags 2.4.1",
  "cap-fs-ext",
@@ -2536,7 +2525,7 @@ dependencies = [
  "fd-lock",
  "io-lifetimes",
  "rustix",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
  "winx",
 ]
 
@@ -3277,7 +3266,7 @@ version = "17.0.0"
 dependencies = [
  "anyhow",
  "cap-std",
- "env_logger 0.10.0",
+ "env_logger",
  "futures",
  "log",
  "once_cell",
@@ -3309,7 +3298,7 @@ dependencies = [
  "filetime",
  "log",
  "once_cell",
- "pretty_env_logger 0.5.0",
+ "pretty_env_logger",
  "rustix",
  "serde",
  "serde_derive",
@@ -3333,11 +3322,11 @@ dependencies = [
  "component-macro-test",
  "component-test-util",
  "criterion",
- "env_logger 0.10.0",
+ "env_logger",
  "filecheck",
  "http",
  "http-body-util",
- "humantime 2.1.0",
+ "humantime",
  "hyper",
  "libc",
  "listenfd",
@@ -3382,7 +3371,7 @@ dependencies = [
  "anyhow",
  "clap",
  "file-per-thread-logger",
- "humantime 2.1.0",
+ "humantime",
  "rayon",
  "tracing-subscriber",
  "wasmtime",
@@ -3452,7 +3441,7 @@ dependencies = [
  "anyhow",
  "clap",
  "cranelift-entity",
- "env_logger 0.10.0",
+ "env_logger",
  "gimli",
  "indexmap 2.0.0",
  "log",
@@ -3475,7 +3464,7 @@ version = "0.0.0"
 dependencies = [
  "arbitrary",
  "component-fuzz-util",
- "env_logger 0.10.0",
+ "env_logger",
  "libfuzzer-sys",
  "wasmparser",
  "wasmprinter",
@@ -3547,7 +3536,7 @@ dependencies = [
  "arbitrary",
  "component-fuzz-util",
  "component-test-util",
- "env_logger 0.10.0",
+ "env_logger",
  "log",
  "rand",
  "rayon",
@@ -3895,7 +3884,7 @@ name = "wiggle-test"
 version = "0.0.0"
 dependencies = [
  "anyhow",
- "env_logger 0.10.0",
+ "env_logger",
  "proptest",
  "thiserror",
  "tracing",
@@ -3998,6 +3987,15 @@ dependencies = [
  "winch-test-macros",
 ]
 
+[[package]]
+name = "windows-core"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+dependencies = [
+ "windows-targets 0.52.0",
+]
+
 [[package]]
 name = "windows-sys"
 version = "0.48.0"
@@ -4132,12 +4130,12 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
 
 [[package]]
 name = "winx"
-version = "0.36.1"
+version = "0.36.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4857cedf8371f690bb6782a3e2b065c54d1b6661be068aaf3eac8b45e813fdf8"
+checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346"
 dependencies = [
  "bitflags 2.4.1",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 4bd0c3fa7..ede457a9e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -133,7 +133,7 @@ authors = ["The Wasmtime Project Developers"]
 edition = "2021"
 # Wasmtime's current policy is that this number can be no larger than the
 # current stable release of Rust minus 2.
-rust-version = "1.72.0"
+rust-version = "1.73.0"
 
 [workspace.lints.rust]
 # Turn on some lints which are otherwise allow-by-default in rustc.
diff --git a/RELEASES.md b/RELEASES.md
index 6ced868ba..78c49dbaa 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -48,6 +48,10 @@ Released 2023-12-20
   when Wasmtime is built from a git checkout.
   [#7610](https://github.com/bytecodealliance/wasmtime/pull/7610)
 
+* Debug intrinsic symbols required by LLDB and GDB have been moved behind a
+  `debug-builtins` feature of the `wasmtime` crate which is enabled by default.
+  [#7626](https://github.com/bytecodealliance/wasmtime/pull/7626)
+
 ### Fixed
 
 * MPK support is now explicitly disabled on AMD-based CPUs since the
diff --git a/build.rs b/build.rs
index 730ca8e83..5e8ef0a78 100644
--- a/build.rs
+++ b/build.rs
@@ -216,6 +216,9 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool {
             "table_copy",
             "table_set",
             "table_get",
+            "memory_grow",
+            "memory_init",
+            "memory_fill",
         ]
         .contains(&testname);
 
@@ -230,7 +233,7 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool {
             }
         }
         if testsuite == "spec_testsuite" {
-            // The official table init and table copy tests are now supported.
+            // The official following tests are supported.
             return !["table_init", "table_copy"].contains(&testname);
         }
 
diff --git a/ci/build-build-matrix.js b/ci/build-build-matrix.js
index 23c2b6ebb..46c7e9bea 100644
--- a/ci/build-build-matrix.js
+++ b/ci/build-build-matrix.js
@@ -55,7 +55,7 @@ const builds = [];
 for (let build of array) {
   // Perform a "deep clone" roundtripping through JSON for a copy of the build
   // that's normal
-  build.rust = 'stable';
+  build.rust = 'default';
   builds.push(JSON.parse(JSON.stringify(build)));
 
   // Next generate a "min" build and add it to the builds list. Min builds
diff --git a/cranelift/codegen/src/isle_prelude.rs b/cranelift/codegen/src/isle_prelude.rs
index 33a7fd424..39bc55027 100644
--- a/cranelift/codegen/src/isle_prelude.rs
+++ b/cranelift/codegen/src/isle_prelude.rs
@@ -819,7 +819,7 @@ macro_rules! isle_common_prelude_methods {
         }
 
         #[inline]
-        fn signed_cond_code(&mut self, cc: &condcodes::IntCC) -> Option<condcodes::IntCC> {
+        fn signed_cond_code(&mut self, cc: &IntCC) -> Option<IntCC> {
             match cc {
                 IntCC::Equal
                 | IntCC::UnsignedGreaterThanOrEqual
diff --git a/cranelift/codegen/src/machinst/isle.rs b/cranelift/codegen/src/machinst/isle.rs
index 6967aa9bc..c1f543b9e 100644
--- a/cranelift/codegen/src/machinst/isle.rs
+++ b/cranelift/codegen/src/machinst/isle.rs
@@ -7,8 +7,8 @@ use std::cell::Cell;
 pub use super::MachLabel;
 use super::RetPair;
 pub use crate::ir::{
-    condcodes, condcodes::CondCode, dynamic_to_fixed, Constant, DynamicStackSlot, ExternalName,
-    FuncRef, GlobalValue, Immediate, SigRef, StackSlot,
+    condcodes::CondCode, dynamic_to_fixed, Constant, DynamicStackSlot, ExternalName, FuncRef,
+    GlobalValue, Immediate, SigRef, StackSlot,
 };
 pub use crate::isa::{unwind::UnwindInst, TargetIsa};
 pub use crate::machinst::{
diff --git a/cranelift/codegen/src/machinst/mod.rs b/cranelift/codegen/src/machinst/mod.rs
index 2d8acd294..3ebcf8b74 100644
--- a/cranelift/codegen/src/machinst/mod.rs
+++ b/cranelift/codegen/src/machinst/mod.rs
@@ -81,6 +81,7 @@ pub use buffer::*;
 pub mod helpers;
 pub use helpers::*;
 pub mod inst_common;
+#[allow(unused_imports)] // not used in all backends right now
 pub use inst_common::*;
 pub mod valueregs;
 pub use reg::*;
diff --git a/cranelift/codegen/src/opts.rs b/cranelift/codegen/src/opts.rs
index 2d05057fc..c24e6190e 100644
--- a/cranelift/codegen/src/opts.rs
+++ b/cranelift/codegen/src/opts.rs
@@ -1,7 +1,6 @@
 //! Optimization driver using ISLE rewrite rules on an egraph.
 
 use crate::egraph::{NewOrExistingInst, OptimizeCtx};
-use crate::ir::condcodes;
 pub use crate::ir::condcodes::{FloatCC, IntCC};
 use crate::ir::dfg::ValueDef;
 pub use crate::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32, Uimm8, V128Imm};
diff --git a/cranelift/codegen/src/opts/arithmetic.isle b/cranelift/codegen/src/opts/arithmetic.isle
index ec40c310f..400da6bab 100644
--- a/cranelift/codegen/src/opts/arithmetic.isle
+++ b/cranelift/codegen/src/opts/arithmetic.isle
@@ -151,3 +151,19 @@
       (subsume (bxor ty (bxor ty a b) (bxor ty c d))))
 (rule (simplify (bxor ty (bxor ty (bxor ty a b) c) d))
       (subsume (bxor ty (bxor ty a b) (bxor ty c d))))
+
+;; Detect people open-coding `mulhi`: (x as big * y as big) >> bits
+;; LLVM doesn't have an intrinsic for it, so you'll see it in code like
+;; <https://github.com/rust-lang/rust/blob/767453eb7ca188e991ac5568c17b984dd4893e77/library/core/src/num/mod.rs#L174-L180>
+(rule (simplify (sshr ty (imul ty (sextend _ x@(value_type half_ty))
+                                  (sextend _ y@(value_type half_ty)))
+                         (iconst_u _ k)))
+      (if-let $true (ty_equal half_ty (ty_half_width ty)))
+      (if-let $true (u64_eq k (ty_bits_u64 half_ty)))
+      (sextend ty (smulhi half_ty x y)))
+(rule (simplify (ushr ty (imul ty (uextend _ x@(value_type half_ty))
+                                  (uextend _ y@(value_type half_ty)))
+                         (iconst_u _ k)))
+      (if-let $true (ty_equal half_ty (ty_half_width ty)))
+      (if-let $true (u64_eq k (ty_bits_u64 half_ty)))
+      (uextend ty (umulhi half_ty x y)))
diff --git a/cranelift/codegen/src/opts/extends.isle b/cranelift/codegen/src/opts/extends.isle
index 17be06f45..a6bb2c562 100644
--- a/cranelift/codegen/src/opts/extends.isle
+++ b/cranelift/codegen/src/opts/extends.isle
@@ -47,8 +47,24 @@
 
 ;; A reduction-of-an-extend back to the same original type is the same as not
 ;; actually doing the extend in the first place.
-(rule (simplify (ireduce ty (sextend _ x @ (value_type ty)))) x)
-(rule (simplify (ireduce ty (uextend _ x @ (value_type ty)))) x)
+(rule (simplify (ireduce ty (sextend _ x @ (value_type ty)))) (subsume x))
+(rule (simplify (ireduce ty (uextend _ x @ (value_type ty)))) (subsume x))
+
+;; A reduction-of-an-extend that's not just to the original type is either:
+;; a reduction of the original if the final type is smaller, or
+(rule (simplify (ireduce (ty_int ty_final) (sextend _ inner@(value_type ty_initial))))
+      (if-let $true (u64_lt (ty_bits_u64 ty_final) (ty_bits_u64 ty_initial)))
+      (ireduce ty_final inner))
+(rule (simplify (ireduce (ty_int ty_final) (uextend _ inner@(value_type ty_initial))))
+      (if-let $true (u64_lt (ty_bits_u64 ty_final) (ty_bits_u64 ty_initial)))
+      (ireduce ty_final inner))
+;; an extension of the original if the final type is larger.
+(rule (simplify (ireduce (ty_int ty_final) (sextend _ inner@(value_type ty_initial))))
+      (if-let $true (u64_lt (ty_bits_u64 ty_initial) (ty_bits_u64 ty_final)))
+      (sextend ty_final inner))
+(rule (simplify (ireduce (ty_int ty_final) (uextend _ inner@(value_type ty_initial))))
+      (if-let $true (u64_lt (ty_bits_u64 ty_initial) (ty_bits_u64 ty_final)))
+      (uextend ty_final inner))
 
 ;; `band`, `bor`, and `bxor` can't affect any bits that aren't set in the one of
 ;; the inputs, so they can be pushed down inside `uextend`s
@@ -58,3 +74,43 @@
       (uextend bigty (bor smallty x y)))
 (rule (simplify (bxor bigty (uextend _ x@(value_type smallty)) (uextend _ y@(value_type smallty))))
       (uextend bigty (bxor smallty x y)))
+
+;; Matches values where `ireducing` them will not actually introduce another
+;; instruction, since other rules will collapse them with the reduction.
+(decl pure multi will_simplify_with_ireduce (Value) Value)
+(rule (will_simplify_with_ireduce x@(uextend _ _)) x)
+(rule (will_simplify_with_ireduce x@(sextend _ _)) x)
+(rule (will_simplify_with_ireduce x@(iconst _ _)) x)
+(rule (will_simplify_with_ireduce x@(unary_op _ _ a))
+      (if-let _ (will_simplify_with_ireduce a))
+      x)
+(rule (will_simplify_with_ireduce x@(binary_op _ _ a b))
+      (if-let _ (will_simplify_with_ireduce a))
+      (if-let _ (will_simplify_with_ireduce b))
+      x)
+
+;; Matches values where the high bits of the input don't affect lower bits of
+;; the output, and thus the inputs can be reduced before the operation rather
+;; than doing the wide operation then reducing afterwards.
+(decl pure multi reducible_modular_op (Value) Value)
+(rule (reducible_modular_op x@(ineg _ _)) x)
+(rule (reducible_modular_op x@(bnot _ _)) x)
+(rule (reducible_modular_op x@(iadd _ _ _)) x)
+(rule (reducible_modular_op x@(isub _ _ _)) x)
+(rule (reducible_modular_op x@(imul _ _ _)) x)
+(rule (reducible_modular_op x@(bor  _ _ _)) x)
+(rule (reducible_modular_op x@(bxor _ _ _)) x)
+(rule (reducible_modular_op x@(band _ _ _)) x)
+
+;; Replace `(small)(x OP y)` with `(small)x OP (small)y` in cases where that's
+;; legal and it reduces the total number of instructions since the reductions
+;; to the arguments simplify further.
+(rule (simplify (ireduce smallty val@(unary_op _ op x)))
+      (if-let _ (reducible_modular_op val))
+      (if-let _ (will_simplify_with_ireduce x))
+      (unary_op smallty op (ireduce smallty x)))
+(rule (simplify (ireduce smallty val@(binary_op _ op x y)))
+      (if-let _ (reducible_modular_op val))
+      (if-let _ (will_simplify_with_ireduce x))
+      (if-let _ (will_simplify_with_ireduce y))
+      (binary_op smallty op (ireduce smallty x) (ireduce smallty y)))
diff --git a/cranelift/codegen/src/prelude_opt.isle b/cranelift/codegen/src/prelude_opt.isle
index e0cd14860..1f02387d2 100644
--- a/cranelift/codegen/src/prelude_opt.isle
+++ b/cranelift/codegen/src/prelude_opt.isle
@@ -120,3 +120,15 @@
 (extractor (sextend_maybe ty val) (sextend_maybe_etor ty val))
 (rule 0 (sextend_maybe ty val) (sextend ty val))
 (rule 1 (sextend_maybe ty val@(value_type ty)) val)
+
+(decl unary_op (Type Opcode Value) Value)
+(extractor (unary_op ty opcode x)
+           (inst_data ty (InstructionData.Unary opcode x)))
+(rule (unary_op ty opcode x)
+      (make_inst ty (InstructionData.Unary opcode x)))
+
+(decl binary_op (Type Opcode Value Value) Value)
+(extractor (binary_op ty opcode x y)
+           (inst_data ty (InstructionData.Binary opcode (value_array_2 x y))))
+(rule (binary_op ty opcode x y)
+      (make_inst ty (InstructionData.Binary opcode (value_array_2_ctor x y))))
diff --git a/cranelift/src/run.rs b/cranelift/src/run.rs
index 1264dfb3b..3912fb793 100644
--- a/cranelift/src/run.rs
+++ b/cranelift/src/run.rs
@@ -8,7 +8,7 @@ use cranelift_filetests::TestFileCompiler;
 use cranelift_native::builder as host_isa_builder;
 use cranelift_reader::{parse_run_command, parse_test, Details, IsaSpec, ParseOptions};
 use std::path::{Path, PathBuf};
-use target_lexicon::Triple;
+use target_lexicon::{Triple, HOST};
 
 /// Execute clif code and verify with test expressions
 #[derive(Parser)]
@@ -106,15 +106,22 @@ fn run_file_contents(file_contents: String) -> Result<()> {
 
 /// Build an ISA based on the current machine running this code (the host)
 fn create_target_isa(isa_spec: &IsaSpec) -> Result<OwnedTargetIsa> {
-    if let IsaSpec::None(flags) = isa_spec {
-        // build an ISA for the current machine
-        let builder = host_isa_builder().map_err(|s| anyhow::anyhow!("{}", s))?;
-        Ok(builder.finish(flags.clone())?)
-    } else {
-        anyhow::bail!(
-            "A target ISA was specified in the file but should not have been--only \
-             the host ISA can be used for running CLIF files"
-        )
+    let builder = host_isa_builder().map_err(|s| anyhow::anyhow!("{}", s))?;
+    match *isa_spec {
+        IsaSpec::None(ref flags) => {
+            // build an ISA for the current machine
+            Ok(builder.finish(flags.clone())?)
+        }
+        IsaSpec::Some(ref isas) => {
+            for isa in isas {
+                if isa.triple().architecture == HOST.architecture {
+                    return Ok(builder.finish(isa.flags().clone())?);
+                }
+            }
+            anyhow::bail!(
+                "The target ISA specified in the file is not compatible with the host ISA"
+            )
+        }
     }
 }
 
diff --git a/crates/wasi-nn/Cargo.toml b/crates/wasi-nn/Cargo.toml
index fbc941f5c..64fe8604d 100644
--- a/crates/wasi-nn/Cargo.toml
+++ b/crates/wasi-nn/Cargo.toml
@@ -24,7 +24,7 @@ wasmtime = { workspace = true, features = ["component-model"] }
 
 # These dependencies are necessary for the wasi-nn implementation:
 tracing = { workspace = true }
-openvino = { version = "0.5.0", features = ["runtime-linking"] }
+openvino = { version = "0.6.0", features = ["runtime-linking"] }
 thiserror = { workspace = true }
 
 [build-dependencies]
diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs
index eb1495619..2295ff7fd 100644
--- a/crates/wasmtime/src/config.rs
+++ b/crates/wasmtime/src/config.rs
@@ -370,6 +370,10 @@ impl Config {
     /// Configures whether DWARF debug information will be emitted during
     /// compilation.
     ///
+    /// Note that the `debug-builtins` compile-time Cargo feature must also be
+    /// enabled for native debuggers such as GDB or LLDB to be able to debug
+    /// guest WebAssembly programs.
+    ///
     /// By default this option is `false`.
     pub fn debug_info(&mut self, enable: bool) -> &mut Self {
         self.tunables.generate_native_debuginfo = enable;
diff --git a/crates/wasmtime/src/lib.rs b/crates/wasmtime/src/lib.rs
index 152475f5d..26b91188f 100644
--- a/crates/wasmtime/src/lib.rs
+++ b/crates/wasmtime/src/lib.rs
@@ -300,6 +300,12 @@
 //!   will attempt to parse DWARF debug information and convert WebAssembly
 //!   addresses to source filenames and line numbers.
 //!
+//! * `debug-builtins` - Enabled by default, this feature includes some built-in
+//!   debugging utilities and symbols for native debuggers such as GDB and LLDB
+//!   to attach to the process Wasmtime is used within. The intrinsics provided
+//!   will enable debugging guest code compiled to WebAssembly. This must also
+//!   be enabled via [`Config::debug_info`] as well for guests.
+//!
 //! More crate features can be found in the [manifest] of Wasmtime itself for
 //! seeing what can be enabled and disabled.
 //!
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 32343ddae..e43309514 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -22,6 +22,9 @@ function(CREATE_TARGET TARGET TARGET_PATH)
 
 	target_include_directories(wasmtime-${TARGET} PUBLIC wasmtime)
 	target_link_libraries(wasmtime-${TARGET} PUBLIC wasmtime)
+	if(APPLE)
+		target_link_libraries(wasmtime-${TARGET} PRIVATE "-framework CoreFoundation")
+	endif()
 	add_test(NAME ${TARGET}-c COMMAND $<TARGET_FILE:wasmtime-${TARGET}> WORKING_DIRECTORY ../..)
 endfunction()
 
diff --git a/fuzz/fuzz_targets/differential.rs b/fuzz/fuzz_targets/differential.rs
index e166fa069..fa3f37dc1 100644
--- a/fuzz/fuzz_targets/differential.rs
+++ b/fuzz/fuzz_targets/differential.rs
@@ -436,7 +436,13 @@ fn winch_supports_module(module: &[u8]) -> bool {
                         | TableFill { .. }
                         | TableGrow { .. }
                         | TableSize { .. }
-                        | TableInit { .. } => {}
+                        | TableInit { .. }
+                        | MemoryCopy { .. }
+                        | MemoryGrow { .. }
+                        | MemoryFill { .. }
+                        | MemoryInit { .. }
+                        | DataDrop { .. }
+                        | MemorySize { .. } => {}
                         _ => {
                             supported = false;
                             break 'main;
diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml
index 073eb4560..2b464c052 100644
--- a/supply-chain/audits.toml
+++ b/supply-chain/audits.toml
@@ -1037,6 +1037,15 @@ criteria = "safe-to-deploy"
 version = "0.2.4"
 notes = "A few tiny blocks of `unsafe` but each of them is very obviously correct."
 
+[[audits.core-foundation-sys]]
+who = "Dan Gohman <dev@sunfishcode.online>"
+criteria = "safe-to-deploy"
+delta = "0.8.4 -> 0.8.6"
+notes = """
+The changes here are all typical bindings updates: new functions, types, and
+constants. I have not audited all the bindings for ABI conformance.
+"""
+
 [[audits.cpufeatures]]
 who = "Alex Crichton <alex@alexcrichton.com>"
 criteria = "safe-to-deploy"
@@ -1404,6 +1413,20 @@ refactorings and such. No new fundamental addition of functionality or
 substantially new unsafe code.
 """
 
+[[audits.iana-time-zone]]
+who = "Dan Gohman <dev@sunfishcode.online>"
+criteria = "safe-to-deploy"
+version = "0.1.59"
+notes = """
+I also manually ran windows-bindgen and confirmed that the output matches
+the bindings checked into the repo.
+"""
+
+[[audits.iana-time-zone-haiku]]
+who = "Dan Gohman <dev@sunfishcode.online>"
+criteria = "safe-to-deploy"
+version = "0.1.2"
+
 [[audits.id-arena]]
 who = "Nick Fitzgerald <fitzgen@gmail.com>"
 criteria = "safe-to-deploy"
@@ -1560,6 +1583,12 @@ criteria = "safe-to-deploy"
 delta = "0.2.148 -> 0.2.149"
 notes = "Lots of new functions and constants for new platforms and nothing out of the ordinary for what one would expect of the `libc` crate."
 
+[[audits.libc]]
+who = "Dan Gohman <dev@sunfishcode.online>"
+criteria = "safe-to-deploy"
+delta = "0.2.149 -> 0.2.151"
+notes = "More new functions, types, and constants, as is usual for the `libc` crate, as well as various minor code cleanups."
+
 [[audits.libfuzzer-sys]]
 who = "Nick Fitzgerald <fitzgen@gmail.com>"
 criteria = "safe-to-run"
@@ -1572,6 +1601,11 @@ criteria = "safe-to-run"
 delta = "0.4.4 -> 0.4.5"
 notes = "I am the author of this crate."
 
+[[audits.libloading]]
+who = "Iceber Gu <caiwei95@hotmail.com>"
+criteria = "safe-to-deploy"
+delta = "0.7.3 -> 0.8.1"
+
 [[audits.libm]]
 who = "Alex Crichton <alex@alexcrichton.com>"
 criteria = "safe-to-deploy"
@@ -1763,6 +1797,11 @@ who = "Andrew Brown <andrew.brown@intel.com>"
 criteria = "safe-to-deploy"
 delta = "0.4.2 -> 0.5.0"
 
+[[audits.openvino]]
+who = "Iceber Gu <caiwei95@hotmail.com>"
+criteria = "safe-to-deploy"
+delta = "0.5.0 -> 0.6.0"
+
 [[audits.openvino-finder]]
 who = "Matthew Tamayo-Rios <matthew@geekbeast.com>"
 criteria = "safe-to-deploy"
@@ -1776,6 +1815,11 @@ who = "Andrew Brown <andrew.brown@intel.com>"
 criteria = "safe-to-deploy"
 delta = "0.4.2 -> 0.5.0"
 
+[[audits.openvino-finder]]
+who = "Iceber Gu <caiwei95@hotmail.com>"
+criteria = "safe-to-deploy"
+delta = "0.5.0 -> 0.6.0"
+
 [[audits.openvino-sys]]
 who = "Matthew Tamayo-Rios <matthew@geekbeast.com>"
 criteria = "safe-to-deploy"
@@ -1789,6 +1833,11 @@ who = "Andrew Brown <andrew.brown@intel.com>"
 criteria = "safe-to-deploy"
 delta = "0.4.2 -> 0.5.0"
 
+[[audits.openvino-sys]]
+who = "Iceber Gu <caiwei95@hotmail.com>"
+criteria = "safe-to-deploy"
+delta = "0.5.0 -> 0.6.0"
+
 [[audits.overload]]
 who = "Pat Hickey <phickey@fastly.com>"
 criteria = "safe-to-deploy"
@@ -3415,6 +3464,12 @@ user-id = 189 # Andrew Gallant (BurntSushi)
 start = "2020-01-11"
 end = "2024-07-15"
 
+[[trusted.windows-core]]
+criteria = "safe-to-deploy"
+user-id = 64539 # Kenny Kerr (kennykerr)
+start = "2021-11-15"
+end = "2025-01-02"
+
 [[trusted.windows-sys]]
 criteria = "safe-to-deploy"
 user-id = 64539 # Kenny Kerr (kennykerr)
diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock
index 273d81f0a..c7107d7ae 100644
--- a/supply-chain/imports.lock
+++ b/supply-chain/imports.lock
@@ -691,6 +691,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.cap-fs-ext]]
+version = "2.0.1"
+when = "2024-01-02"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.cap-net-ext]]
 version = "2.0.0"
 when = "2023-06-30"
@@ -698,6 +705,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.cap-net-ext]]
+version = "2.0.1"
+when = "2024-01-02"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.cap-primitives]]
 version = "2.0.0"
 when = "2023-06-30"
@@ -705,6 +719,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.cap-primitives]]
+version = "2.0.1"
+when = "2024-01-02"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.cap-rand]]
 version = "2.0.0"
 when = "2023-06-30"
@@ -712,6 +733,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.cap-rand]]
+version = "2.0.1"
+when = "2024-01-02"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.cap-std]]
 version = "2.0.0"
 when = "2023-06-30"
@@ -719,6 +747,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.cap-std]]
+version = "2.0.1"
+when = "2024-01-02"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.cap-tempfile]]
 version = "2.0.0"
 when = "2023-06-30"
@@ -726,6 +761,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.cap-tempfile]]
+version = "2.0.1"
+when = "2024-01-02"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.cap-time-ext]]
 version = "2.0.0"
 when = "2023-06-30"
@@ -733,6 +775,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.cap-time-ext]]
+version = "2.0.1"
+when = "2024-01-02"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.clap]]
 version = "4.3.12"
 when = "2023-07-14"
@@ -761,6 +810,13 @@ user-id = 6743
 user-login = "epage"
 user-name = "Ed Page"
 
+[[publisher.core-foundation-sys]]
+version = "0.8.4"
+when = "2023-04-03"
+user-id = 5946
+user-login = "jrmuizel"
+user-name = "Jeff Muizelaar"
+
 [[publisher.cranelift]]
 version = "0.101.2"
 when = "2023-10-26"
@@ -1088,6 +1144,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.errno]]
+version = "0.3.8"
+when = "2023-11-28"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.fd-lock]]
 version = "4.0.0"
 when = "2023-06-30"
@@ -1095,6 +1158,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.fd-lock]]
+version = "4.0.2"
+when = "2023-12-29"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.filecheck]]
 version = "0.5.0"
 when = "2020-03-17"
@@ -1109,6 +1179,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.fs-set-times]]
+version = "0.20.1"
+when = "2023-12-01"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.hashbrown]]
 version = "0.14.0"
 when = "2023-06-05"
@@ -1137,6 +1214,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.io-extras]]
+version = "0.18.1"
+when = "2023-12-01"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.io-lifetimes]]
 version = "2.0.2"
 when = "2023-06-30"
@@ -1151,6 +1235,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.is-terminal]]
+version = "0.4.10"
+when = "2023-12-28"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.itoa]]
 version = "1.0.1"
 when = "2021-12-12"
@@ -1179,6 +1270,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.linux-raw-sys]]
+version = "0.4.12"
+when = "2023-11-30"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.memchr]]
 version = "2.5.0"
 when = "2022-04-30"
@@ -1249,6 +1347,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.rustix]]
+version = "0.38.28"
+when = "2023-12-09"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.ryu]]
 version = "1.0.9"
 when = "2021-12-12"
@@ -1325,6 +1430,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.system-interface]]
+version = "0.26.1"
+when = "2024-01-02"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.target-lexicon]]
 version = "0.12.3"
 when = "2022-02-01"
@@ -2293,6 +2405,13 @@ when = "2023-12-01"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.windows-core]]
+version = "0.52.0"
+when = "2023-11-15"
+user-id = 64539
+user-login = "kennykerr"
+user-name = "Kenny Kerr"
+
 [[publisher.windows-sys]]
 version = "0.48.0"
 when = "2023-03-31"
@@ -2426,6 +2545,13 @@ user-id = 6825
 user-login = "sunfishcode"
 user-name = "Dan Gohman"
 
+[[publisher.winx]]
+version = "0.36.3"
+when = "2023-12-01"
+user-id = 6825
+user-login = "sunfishcode"
+user-name = "Dan Gohman"
+
 [[publisher.wit-bindgen]]
 version = "0.13.0"
 when = "2023-10-18"
@@ -2706,6 +2832,16 @@ who = "David Cook <dcook@divviup.org>"
 criteria = "safe-to-deploy"
 version = "0.7.1"
 
+[[audits.mozilla.wildcard-audits.core-foundation-sys]]
+who = "Bobby Holley <bobbyholley@gmail.com>"
+criteria = "safe-to-deploy"
+user-id = 5946 # Jeff Muizelaar (jrmuizel)
+start = "2020-10-14"
+end = "2023-05-04"
+renew = false
+notes = "I've reviewed every source contribution that was neither authored nor reviewed by Mozilla."
+aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
+
 [[audits.mozilla.wildcard-audits.unicode-segmentation]]
 who = "Manish Goregaokar <manishsmail@gmail.com>"
 criteria = "safe-to-deploy"
@@ -2733,6 +2869,25 @@ end = "2024-05-03"
 notes = "All code written or reviewed by Manish"
 aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
 
+[[audits.mozilla.audits.android_system_properties]]
+who = "Nicolas Silva <nical@fastmail.com>"
+criteria = "safe-to-deploy"
+version = "0.1.2"
+notes = "I wrote this crate, reviewed by jimb. It is mostly a Rust port of some C++ code we already ship."
+aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
+
+[[audits.mozilla.audits.android_system_properties]]
+who = "Mike Hommey <mh+mozilla@glandium.org>"
+criteria = "safe-to-deploy"
+delta = "0.1.2 -> 0.1.4"
+aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
+
+[[audits.mozilla.audits.android_system_properties]]
+who = "Mike Hommey <mh+mozilla@glandium.org>"
+criteria = "safe-to-deploy"
+delta = "0.1.4 -> 0.1.5"
+aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
+
 [[audits.mozilla.audits.autocfg]]
 who = "Josh Stone <jistone@redhat.com>"
 criteria = "safe-to-deploy"
@@ -2804,6 +2959,18 @@ criteria = "safe-to-deploy"
 delta = "1.3.0 -> 1.4.0"
 aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
 
+[[audits.mozilla.audits.cc]]
+who = "Mike Hommey <mh+mozilla@glandium.org>"
+criteria = "safe-to-deploy"
+delta = "1.0.73 -> 1.0.78"
+aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
+
+[[audits.mozilla.audits.cc]]
+who = "Jan-Erik Rediger <jrediger@mozilla.com>"
+criteria = "safe-to-deploy"
+delta = "1.0.78 -> 1.0.83"
+aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml"
+
 [[audits.mozilla.audits.crypto-common]]
 who = "Mike Hommey <mh+mozilla@glandium.org>"
 criteria = "safe-to-deploy"
diff --git a/winch/codegen/src/codegen/env.rs b/winch/codegen/src/codegen/env.rs
index 09293f228..48a690cf1 100644
--- a/winch/codegen/src/codegen/env.rs
+++ b/winch/codegen/src/codegen/env.rs
@@ -9,8 +9,8 @@ use std::collections::{
 };
 use wasmparser::BlockType;
 use wasmtime_environ::{
-    FuncIndex, GlobalIndex, ModuleTranslation, ModuleTypesBuilder, PtrSize, TableIndex, TablePlan,
-    TypeConvert, TypeIndex, VMOffsets, WasmFuncType, WasmHeapType, WasmType,
+    FuncIndex, GlobalIndex, MemoryIndex, ModuleTranslation, ModuleTypesBuilder, PtrSize,
+    TableIndex, TablePlan, TypeConvert, TypeIndex, VMOffsets, WasmFuncType, WasmHeapType, WasmType,
 };
 
 /// Table metadata.
@@ -20,15 +20,29 @@ pub struct TableData {
     pub offset: u32,
     /// The offset to the current elements field.
     pub current_elems_offset: u32,
-    /// If the table is imported, return the base
-    /// offset of the `from` field in `VMTableImport`.
-    pub base: Option<u32>,
+    /// If the table is imported, this field contains the offset to locate the
+    /// base of the table data.
+    pub import_from: Option<u32>,
     /// The size of the table elements.
     pub(crate) element_size: OperandSize,
     /// The size of the current elements field.
     pub(crate) current_elements_size: OperandSize,
 }
 
+/// Heap metadata.
+#[derive(Debug, Copy, Clone)]
+pub struct HeapData {
+    /// The offset to the base of the heap.
+    pub offset: u32,
+    /// The offset to the current length field.
+    pub current_length_offset: u32,
+    /// If the heap is imported, this field contains the offset to locate the
+    /// base of the heap.
+    pub import_from: Option<u32>,
+    /// The memory type (32 or 64).
+    pub ty: WasmType,
+}
+
 /// A function callee.
 /// It categorizes how the callee should be treated
 /// when performing the call.
@@ -95,6 +109,7 @@ pub struct FuncEnv<'a, 'translation: 'a, 'data: 'translation, P: PtrSize> {
     pub types: &'translation ModuleTypesBuilder,
     /// Track resolved table information.
     resolved_tables: HashMap<TableIndex, TableData>,
+    resolved_heaps: HashMap<MemoryIndex, HeapData>,
 }
 
 pub fn ptr_type_from_ptr_size(size: u8) -> WasmType {
@@ -115,6 +130,7 @@ impl<'a, 'translation, 'data, P: PtrSize> FuncEnv<'a, 'translation, 'data, P> {
             translation,
             types,
             resolved_tables: HashMap::new(),
+            resolved_heaps: HashMap::new(),
         }
     }
 
@@ -222,7 +238,7 @@ impl<'a, 'translation, 'data, P: PtrSize> FuncEnv<'a, 'translation, 'data, P> {
                     };
 
                 *entry.insert(TableData {
-                    base: from_offset,
+                    import_from: from_offset,
                     offset: base_offset,
                     current_elems_offset,
                     element_size: OperandSize::from_bytes(self.vmoffsets.ptr.size()),
@@ -234,6 +250,48 @@ impl<'a, 'translation, 'data, P: PtrSize> FuncEnv<'a, 'translation, 'data, P> {
         }
     }
 
+    /// Resolved a [HeapData] from a [MemoryIndex].
+    // TODO: (@saulecabrera)
+    // Handle shared memories when implementing support for Wasm Threads.
+    pub fn resolve_heap(&mut self, index: MemoryIndex) -> HeapData {
+        match self.resolved_heaps.entry(index) {
+            Occupied(entry) => *entry.get(),
+            Vacant(entry) => {
+                let (import_from, base_offset, current_length_offset) =
+                    match self.translation.module.defined_memory_index(index) {
+                        Some(defined) => {
+                            let owned = self.translation.module.owned_memory_index(defined);
+                            (
+                                None,
+                                self.vmoffsets.vmctx_vmmemory_definition_base(owned),
+                                self.vmoffsets
+                                    .vmctx_vmmemory_definition_current_length(owned),
+                            )
+                        }
+                        None => (
+                            Some(self.vmoffsets.vmctx_vmmemory_import_from(index)),
+                            self.vmoffsets.ptr.vmmemory_definition_base().into(),
+                            self.vmoffsets
+                                .ptr
+                                .vmmemory_definition_current_length()
+                                .into(),
+                        ),
+                    };
+
+                *entry.insert(HeapData {
+                    offset: base_offset,
+                    import_from,
+                    current_length_offset,
+                    ty: if self.translation.module.memory_plans[index].memory.memory64 {
+                        WasmType::I64
+                    } else {
+                        WasmType::I32
+                    },
+                })
+            }
+        }
+    }
+
     /// Get a [`TablePlan`] from a [`TableIndex`].
     pub fn table_plan(&mut self, index: TableIndex) -> &TablePlan {
         &self.translation.module.table_plans[index]
diff --git a/winch/codegen/src/isa/aarch64/masm.rs b/winch/codegen/src/isa/aarch64/masm.rs
index 74ce2d96e..714913489 100644
--- a/winch/codegen/src/isa/aarch64/masm.rs
+++ b/winch/codegen/src/isa/aarch64/masm.rs
@@ -1,7 +1,7 @@
 use super::{abi::Aarch64ABI, address::Address, asm::Assembler, regs};
 use crate::{
     abi::{self, local::LocalSlot},
-    codegen::{ptr_type_from_ptr_size, CodeGenContext, TableData},
+    codegen::{ptr_type_from_ptr_size, CodeGenContext, HeapData, TableData},
     isa::reg::Reg,
     masm::{
         CalleeKind, DivKind, ExtendKind, FloatCmpKind, Imm as I, IntCmpKind,
@@ -116,6 +116,10 @@ impl Masm for MacroAssembler {
         todo!()
     }
 
+    fn memory_size(&mut self, _heap_data: &HeapData, _context: &mut CodeGenContext) {
+        todo!()
+    }
+
     fn address_from_sp(&self, _offset: SPOffset) -> Self::Address {
         todo!()
     }
diff --git a/winch/codegen/src/isa/x64/masm.rs b/winch/codegen/src/isa/x64/masm.rs
index c5ea1ac88..e01eb6d34 100644
--- a/winch/codegen/src/isa/x64/masm.rs
+++ b/winch/codegen/src/isa/x64/masm.rs
@@ -27,7 +27,7 @@ use cranelift_codegen::{
     isa::x64::settings as x64_settings, settings, Final, MachBufferFinalized, MachLabel,
 };
 
-use wasmtime_environ::PtrSize;
+use wasmtime_environ::{PtrSize, WasmType, WASM_PAGE_SIZE};
 
 /// x64 MacroAssembler.
 pub(crate) struct MacroAssembler {
@@ -137,7 +137,7 @@ impl Masm for MacroAssembler {
         let bound = context.any_gpr(self);
         let tmp = context.any_gpr(self);
 
-        if let Some(offset) = table_data.base {
+        if let Some(offset) = table_data.import_from {
             // If the table data declares a particular offset base,
             // load the address into a register to further use it as
             // the table address.
@@ -192,7 +192,7 @@ impl Masm for MacroAssembler {
         let scratch = regs::scratch();
         let size = context.any_gpr(self);
 
-        if let Some(offset) = table_data.base {
+        if let Some(offset) = table_data.import_from {
             self.asm
                 .mov_mr(&self.address_at_vmctx(offset), scratch, self.ptr_size);
         } else {
@@ -206,6 +206,44 @@ impl Masm for MacroAssembler {
         context.stack.push(TypedReg::i32(size).into());
     }
 
+    fn memory_size(&mut self, heap_data: &crate::codegen::HeapData, context: &mut CodeGenContext) {
+        let size_reg = context.any_gpr(self);
+        let scratch = regs::scratch();
+        let vmctx = <Self::ABI as ABI>::vmctx_reg();
+
+        let base = if let Some(offset) = heap_data.import_from {
+            self.asm
+                .mov_mr(&self.address_at_vmctx(offset), scratch, self.ptr_size);
+            scratch
+        } else {
+            vmctx
+        };
+
+        let size_addr = Address::offset(base, heap_data.current_length_offset);
+        self.asm.mov_mr(&size_addr, size_reg, self.ptr_size);
+        // Prepare the stack to emit a shift to get the size in pages rather
+        // than in bytes.
+        context
+            .stack
+            .push(TypedReg::new(heap_data.ty, size_reg).into());
+
+        // Since the page size is a power-of-two, verify that 2^16, equals the
+        // defined constant. This is mostly a safeguard in case the constant
+        // value ever changes.
+        let pow = 16;
+        debug_assert_eq!(2u32.pow(pow), WASM_PAGE_SIZE);
+
+        // Ensure that the constant is correctly typed according to the heap
+        // type to reduce register pressure when emitting the shift operation.
+        match heap_data.ty {
+            WasmType::I32 => context.stack.push(Val::i32(pow as i32)),
+            WasmType::I64 => context.stack.push(Val::i64(pow as i64)),
+            _ => unreachable!(),
+        }
+
+        self.shift(context, ShiftKind::ShrU, heap_data.ty.into());
+    }
+
     fn address_from_sp(&self, offset: SPOffset) -> Self::Address {
         Address::offset(regs::rsp(), self.sp_offset - offset.as_u32())
     }
diff --git a/winch/codegen/src/masm.rs b/winch/codegen/src/masm.rs
index 42ea92f97..33d1cc940 100644
--- a/winch/codegen/src/masm.rs
+++ b/winch/codegen/src/masm.rs
@@ -1,5 +1,5 @@
 use crate::abi::{self, align_to, LocalSlot};
-use crate::codegen::{ptr_type_from_ptr_size, CodeGenContext, TableData};
+use crate::codegen::{ptr_type_from_ptr_size, CodeGenContext, HeapData, TableData};
 use crate::isa::reg::Reg;
 use cranelift_codegen::{ir::LibCall, Final, MachBufferFinalized, MachLabel};
 use std::{fmt::Debug, ops::Range};
@@ -375,6 +375,9 @@ pub(crate) trait MacroAssembler {
     /// Retrieves the size of the table, pushing the result to the value stack.
     fn table_size(&mut self, table_data: &TableData, context: &mut CodeGenContext);
 
+    /// Retrieves the size of the memory, pushing the result to the value stack.
+    fn memory_size(&mut self, heap_data: &HeapData, context: &mut CodeGenContext);
+
     /// Constructs an address with an offset that is relative to the
     /// current position of the stack pointer (e.g. [sp + (sp_offset -
     /// offset)].
diff --git a/winch/codegen/src/visitor.rs b/winch/codegen/src/visitor.rs
index a82ecce9a..4afc9a895 100644
--- a/winch/codegen/src/visitor.rs
+++ b/winch/codegen/src/visitor.rs
@@ -16,7 +16,7 @@ use smallvec::SmallVec;
 use wasmparser::BrTable;
 use wasmparser::{BlockType, Ieee32, Ieee64, VisitOperator};
 use wasmtime_environ::{
-    FuncIndex, GlobalIndex, TableIndex, TableStyle, TypeIndex, WasmHeapType, WasmType,
+    FuncIndex, GlobalIndex, MemoryIndex, TableIndex, TableStyle, TypeIndex, WasmHeapType, WasmType,
     FUNCREF_INIT_BIT,
 };
 
@@ -179,6 +179,12 @@ macro_rules! def_unsupported {
     (emit TableSize $($rest:tt)*) => {};
     (emit TableFill $($rest:tt)*) => {};
     (emit ElemDrop $($rest:tt)*) => {};
+    (emit MemoryInit $($rest:tt)*) => {};
+    (emit MemoryCopy $($rest:tt)*) => {};
+    (emit DataDrop $($rest:tt)*) => {};
+    (emit MemoryFill $($rest:tt)*) => {};
+    (emit MemorySize $($rest:tt)*) => {};
+    (emit MemoryGrow $($rest:tt)*) => {};
 
     (emit $unsupported:tt $($rest:tt)*) => {$($rest)*};
 }
@@ -1239,6 +1245,97 @@ where
         });
     }
 
+    fn visit_memory_init(&mut self, data_index: u32, mem: u32) {
+        debug_assert!(self.context.stack.len() >= 3);
+        let ptr_type = self.env.ptr_type();
+        let at = self.context.stack.len() - 3;
+        let vmctx = TypedReg::new(ptr_type, <M::ABI as ABI>::vmctx_reg());
+        self.context.stack.insert_many(
+            at,
+            [
+                vmctx.into(),
+                mem.try_into().unwrap(),
+                data_index.try_into().unwrap(),
+            ],
+        );
+        FnCall::emit::<M, M::Ptr, _>(self.masm, &mut self.context, |cx| {
+            Callee::Builtin(cx.builtins.memory_init::<M::ABI, M::Ptr>())
+        });
+    }
+
+    fn visit_memory_copy(&mut self, dst_mem: u32, src_mem: u32) {
+        // At this point, the stack is expected to contain:
+        //     [ dst_offset, src_offset, len ]
+        // The following code inserts the missing params, so that stack contains:
+        //     [ vmctx, dst_mem, dst_offset, src_mem, src_offset, len ]
+        // Which is the order expected by the builtin function.
+        debug_assert!(self.context.stack.len() >= 3);
+        let ptr_type = self.env.ptr_type();
+        let vmctx = TypedReg::new(ptr_type, <M::ABI as ABI>::vmctx_reg());
+        let at = self.context.stack.len() - 2;
+        self.context
+            .stack
+            .insert_many(at, [src_mem.try_into().unwrap()]);
+
+        // One element was inserted above, so instead of 3, we use 4.
+        let at = self.context.stack.len() - 4;
+        self.context
+            .stack
+            .insert_many(at, [vmctx.into(), dst_mem.try_into().unwrap()]);
+
+        FnCall::emit::<M, M::Ptr, _>(self.masm, &mut self.context, |cx| {
+            Callee::Builtin(cx.builtins.memory_copy::<M::ABI, M::Ptr>())
+        });
+    }
+
+    fn visit_memory_fill(&mut self, mem: u32) {
+        debug_assert!(self.context.stack.len() >= 3);
+        let ptr_type = self.env.ptr_type();
+        let vmctx = TypedReg::new(ptr_type, <M::ABI as ABI>::vmctx_reg());
+        let at = self.context.stack.len() - 3;
+
+        self.context
+            .stack
+            .insert_many(at, [vmctx.into(), mem.try_into().unwrap()]);
+
+        FnCall::emit::<M, M::Ptr, _>(self.masm, &mut self.context, |cx| {
+            Callee::Builtin(cx.builtins.memory_fill::<M::ABI, M::Ptr>())
+        });
+    }
+
+    fn visit_memory_size(&mut self, mem: u32, _: u8) {
+        let heap = self.env.resolve_heap(MemoryIndex::from_u32(mem));
+        self.masm.memory_size(&heap, &mut self.context);
+    }
+
+    fn visit_memory_grow(&mut self, mem: u32, _: u8) {
+        debug_assert!(self.context.stack.len() >= 1);
+        let ptr_type = self.env.ptr_type();
+        let vmctx = TypedReg::new(ptr_type, <M::ABI as ABI>::vmctx_reg());
+        let at = self.context.stack.len() - 1;
+        // The stack at this point contains: [ delta ]
+        // The desired state is
+        //   [ vmctx, delta, index ]
+        self.context.stack.insert_many(at, [vmctx.into()]);
+        self.context.stack.extend([mem.try_into().unwrap()]);
+
+        FnCall::emit::<M, M::Ptr, _>(self.masm, &mut self.context, |cx| {
+            Callee::Builtin(cx.builtins.memory32_grow::<M::ABI, M::Ptr>())
+        });
+    }
+
+    fn visit_data_drop(&mut self, data_index: u32) {
+        let ptr_type = self.env.ptr_type();
+        let vmctx = TypedReg::new(ptr_type, <M::ABI as ABI>::vmctx_reg());
+        self.context
+            .stack
+            .extend([vmctx.into(), data_index.try_into().unwrap()]);
+
+        FnCall::emit::<M, M::Ptr, _>(self.masm, &mut self.context, |cx| {
+            Callee::Builtin(cx.builtins.data_drop::<M::ABI, M::Ptr>())
+        });
+    }
+
     fn visit_nop(&mut self) {}
 
     fn visit_if(&mut self, blockty: BlockType) {


Test patch:
diff --git a/cranelift/filetests/filetests/egraph/arithmetic.clif b/cranelift/filetests/filetests/egraph/arithmetic.clif
index 1abdeae1e..2e64d73d8 100644
--- a/cranelift/filetests/filetests/egraph/arithmetic.clif
+++ b/cranelift/filetests/filetests/egraph/arithmetic.clif
@@ -250,3 +250,108 @@ block0(v1: f32, v2: f32):
 
 ; check: v6 = fmul v1, v2
 ; check: return v6
+
+function %manual_smulhi_32(i32, i32) -> i32 {
+block0(v0: i32, v1: i32):
+    v2 = sextend.i64 v0
+    v3 = sextend.i64 v1
+    v4 = imul v2, v3
+    v5 = iconst.i32 32
+    v6 = sshr v4, v5
+    v7 = ireduce.i32 v6
+    return v7
+}
+
+; check: v8 = smulhi v0, v1
+; check: return v8
+
+function %manual_smulhi_64(i64, i64) -> i64 {
+block0(v0: i64, v1: i64):
+    v2 = sextend.i128 v0
+    v3 = sextend.i128 v1
+    v4 = imul v2, v3
+    v5 = iconst.i32 64
+    v6 = sshr v4, v5
+    v7 = ireduce.i64 v6
+    return v7
+}
+
+; check: v8 = smulhi v0, v1
+; check: return v8
+
+function %manual_umulhi_32(i32, i32) -> i32 {
+block0(v0: i32, v1: i32):
+    v2 = uextend.i64 v0
+    v3 = uextend.i64 v1
+    v4 = imul v2, v3
+    v5 = iconst.i32 32
+    v6 = ushr v4, v5
+    v7 = ireduce.i32 v6
+    return v7
+}
+
+; check: v8 = umulhi v0, v1
+; check: return v8
+
+function %manual_umulhi_64(i64, i64) -> i64 {
+block0(v0: i64, v1: i64):
+    v2 = uextend.i128 v0
+    v3 = uextend.i128 v1
+    v4 = imul v2, v3
+    v5 = iconst.i32 64
+    v6 = ushr v4, v5
+    v7 = ireduce.i64 v6
+    return v7
+}
+
+; check: v8 = umulhi v0, v1
+; check: return v8
+
+function %u64_widening_mul(i64, i64, i64) {
+block0(v0: i64, v1: i64, v2: i64):
+    v3 = uextend.i128 v1
+    v4 = uextend.i128 v2
+    v5 = imul v3, v4
+    v6 = iconst.i32 64
+    v7 = ushr v5, v6
+    v8 = ireduce.i64 v7
+    v9 = ireduce.i64 v5
+    store.i64 v9, v0
+    store.i64 v8, v0+8
+    return
+}
+
+; check: v15 = imul v1, v2
+; check: store v15, v0
+; check: v10 = umulhi v1, v2
+; check: store v10, v0+8
+
+function %char_plus_one(i8) -> i8 {
+block0(v0: i8):
+    v1 = sextend.i32 v0
+    v2 = iconst.i32 257
+    v3 = iadd v1, v2
+    v4 = ireduce.i8 v3
+    return v4
+}
+
+; check: v7 = iconst.i8 1
+; check: v8 = iadd v0, v7  ; v7 = 1
+; check: return v8
+
+;; Adding three `short`s together and storing them in a `short`,
+;; which in C involves extending them to `int`s in the middle.
+function %extend_iadd_iadd_reduce(i16, i16, i16) -> i16 {
+block0(v0: i16, v1: i16, v2: i16):
+    v3 = sextend.i32 v0
+    v4 = sextend.i32 v1
+    v5 = sextend.i32 v2
+    v6 = iadd v3, v4
+    v7 = iadd v6, v5
+    v8 = ireduce.i16 v7
+    return v8
+}
+
+; check: v12 = iadd v0, v1
+; check: v15 = iadd v12, v2
+; check: return v15
diff --git a/cranelift/filetests/filetests/egraph/extends.clif b/cranelift/filetests/filetests/egraph/extends.clif
index 6562dc58d..4859d8d8d 100644
--- a/cranelift/filetests/filetests/egraph/extends.clif
+++ b/cranelift/filetests/filetests/egraph/extends.clif
@@ -94,6 +94,46 @@ block0(v1: i32):
 
 ; check: return v1
 
+function %sextend_then_reduce_smaller(i32) -> i16 {
+block0(v1: i32):
+    v2 = sextend.i64 v1
+    v3 = ireduce.i16 v2
+    return v3
+}
+
+; check: v4 = ireduce.i16 v1
+; check: return v4
+
+function %uextend_then_reduce_smaller(i32) -> i16 {
+block0(v1: i32):
+    v2 = uextend.i64 v1
+    v3 = ireduce.i16 v2
+    return v3
+}
+
+; check: v4 = ireduce.i16 v1
+; check: return v4
+
+function %sextend_then_reduce_partially(i16) -> i32 {
+block0(v1: i16):
+    v2 = sextend.i64 v1
+    v3 = ireduce.i32 v2
+    return v3
+}
+
+; check: v4 = sextend.i32 v1
+; check: return v4
+
+function %uextend_then_reduce_partially(i16) -> i32 {
+block0(v1: i16):
+    v2 = uextend.i64 v1
+    v3 = ireduce.i32 v2
+    return v3
+}
+
+; check: v4 = uextend.i32 v1
+; check: return v4
+
 function %sextend_then_slt_zero(i8) -> i8 {
 block0(v0: i8):
     v1 = sextend.i16 v0
@@ -118,3 +158,72 @@ block0(v0: i8):
 ; check: v5 = icmp ne v0, v4
 ; check: return v5
 
+function %extend_imul_reduce(i64, i64) -> i64 {
+block0(v0: i64, v1: i64):
+    v2 = uextend.i128 v0
+    v3 = uextend.i128 v1
+    v4 = imul v2, v3
+    v5 = ireduce.i64 v4
+    return v5
+}
+
+; check: v8 = imul v0, v1
+; check: return v8
+
+function %extend_iadd_reduce(i16, i16) -> i16 {
+block0(v0: i16, v1: i16):
+    v2 = sextend.i32 v0
+    v3 = sextend.i32 v1
+    v4 = iadd v2, v3
+    v5 = ireduce.i16 v4
+    return v5
+}
+
+; check: v8 = iadd v0, v1
+; check: return v8
+
+function %extend_bxor_reduce(i64, i64) -> i64 {
+block0(v0: i64, v1: i64):
+    v2 = uextend.i128 v0
+    v3 = uextend.i128 v1
+    v4 = bxor v2, v3
+    v5 = ireduce.i64 v4
+    return v5
+}
+
+; check: v6 = bxor v0, v1
+; check: return v6
+
+function %extend_band_reduce(i16, i16) -> i16 {
+block0(v0: i16, v1: i16):
+    v2 = sextend.i32 v0
+    v3 = sextend.i32 v1
+    v4 = band v2, v3
+    v5 = ireduce.i16 v4
+    return v5
+}
+
+; check: v8 = band v0, v1
+; check: return v8
+
+function %extend_ineg_reduce(i64) -> i64 {
+block0(v0: i64):
+    v1 = sextend.i128 v0
+    v2 = ineg v1
+    v3 = ireduce.i64 v2
+    return v3
+}
+
+; check: v5 = ineg v0
+; check: return v5
+
+function %extend_bnot_reduce(i16) -> i16 {
+block0(v0: i16):
+    v1 = uextend.i32 v0
+    v2 = bnot v1
+    v3 = ireduce.i16 v2
+    return v3
+}
+
+; check: v5 = bnot v0
+; check: return v5
diff --git a/tests/misc_testsuite/winch/memory_fill.wast b/tests/misc_testsuite/winch/memory_fill.wast
new file mode 100644
index 000000000..b37896de3
--- /dev/null
+++ b/tests/misc_testsuite/winch/memory_fill.wast
@@ -0,0 +1,57 @@
+(module
+  (memory 1 1)
+  
+  (func (export "test")
+    (memory.fill (i32.const 0xFF00) (i32.const 0x55) (i32.const 256))))
+(invoke "test")
+
+(module
+  (memory 1 1)
+  
+  (func (export "test")
+    (memory.fill (i32.const 0xFF00) (i32.const 0x55) (i32.const 257))))
+(assert_trap (invoke "test") "out of bounds memory access")
+
+(module
+  (memory 1 1)
+  
+  (func (export "test")
+    (memory.fill (i32.const 0xFFFFFF00) (i32.const 0x55) (i32.const 257))))
+(assert_trap (invoke "test") "out of bounds memory access")
+
+(module
+  (memory 1 1)
+  
+  (func (export "test")
+    (memory.fill (i32.const 0x12) (i32.const 0x55) (i32.const 0))))
+(invoke "test")
+
+(module
+  (memory 1 1)
+  
+  (func (export "test")
+    (memory.fill (i32.const 0x10000) (i32.const 0x55) (i32.const 0))))
+(invoke "test")
+
+(module
+  (memory 1 1)
+  
+  (func (export "test")
+    (memory.fill (i32.const 0x20000) (i32.const 0x55) (i32.const 0))))
+(assert_trap (invoke "test") "out of bounds memory access")
+
+(module
+  (memory 1 1)
+  
+  (func (export "test")
+    (memory.fill (i32.const 0x1) (i32.const 0xAA) (i32.const 0xFFFE))))
+(invoke "test")
+
+
+(module
+  (memory 1 1)
+  
+  (func (export "test")
+     (memory.fill (i32.const 0x12) (i32.const 0x55) (i32.const 10))
+     (memory.fill (i32.const 0x15) (i32.const 0xAA) (i32.const 4))))
+(invoke "test")
diff --git a/tests/misc_testsuite/winch/memory_grow.wast b/tests/misc_testsuite/winch/memory_grow.wast
new file mode 100644
index 000000000..7d763d62f
--- /dev/null
+++ b/tests/misc_testsuite/winch/memory_grow.wast
@@ -0,0 +1,211 @@
+(module
+  (memory 0)
+  (func (export "grow") (param i32) (result i32) (memory.grow (local.get 0)))
+)
+
+(assert_return (invoke "grow" (i32.const 0)) (i32.const 0))
+(assert_return (invoke "grow" (i32.const 1)) (i32.const 0))
+(assert_return (invoke "grow" (i32.const 0)) (i32.const 1))
+(assert_return (invoke "grow" (i32.const 2)) (i32.const 1))
+(assert_return (invoke "grow" (i32.const 800)) (i32.const 3))
+(assert_return (invoke "grow" (i32.const 0x10000)) (i32.const -1))
+(assert_return (invoke "grow" (i32.const 64736)) (i32.const -1))
+(assert_return (invoke "grow" (i32.const 1)) (i32.const 803))
+
+(module
+  (memory 0 10)
+  (func (export "grow") (param i32) (result i32) (memory.grow (local.get 0)))
+)
+
+(assert_return (invoke "grow" (i32.const 0)) (i32.const 0))
+(assert_return (invoke "grow" (i32.const 1)) (i32.const 0))
+(assert_return (invoke "grow" (i32.const 1)) (i32.const 1))
+(assert_return (invoke "grow" (i32.const 2)) (i32.const 2))
+(assert_return (invoke "grow" (i32.const 6)) (i32.const 4))
+(assert_return (invoke "grow" (i32.const 0)) (i32.const 10))
+(assert_return (invoke "grow" (i32.const 1)) (i32.const -1))
+(assert_return (invoke "grow" (i32.const 0x10000)) (i32.const -1))
+
+;; As the argument of control constructs and instructions
+
+(module
+  (memory 1)
+
+  (func (export "as-br-value") (result i32)
+    (block (result i32) (br 0 (memory.grow (i32.const 0))))
+  )
+
+  (func (export "as-br_if-cond")
+    (block (br_if 0 (memory.grow (i32.const 0))))
+  )
+  (func (export "as-br_if-value") (result i32)
+    (block (result i32)
+      (drop (br_if 0 (memory.grow (i32.const 0)) (i32.const 1))) (i32.const 7)
+    )
+  )
+  (func (export "as-br_if-value-cond") (result i32)
+    (block (result i32)
+      (drop (br_if 0 (i32.const 6) (memory.grow (i32.const 0)))) (i32.const 7)
+    )
+  )
+
+  (func (export "as-br_table-index")
+    (block (br_table 0 0 0 (memory.grow (i32.const 0))))
+  )
+  (func (export "as-br_table-value") (result i32)
+    (block (result i32)
+      (br_table 0 0 0 (memory.grow (i32.const 0)) (i32.const 1)) (i32.const 7)
+    )
+  )
+  (func (export "as-br_table-value-index") (result i32)
+    (block (result i32)
+      (br_table 0 0 (i32.const 6) (memory.grow (i32.const 0))) (i32.const 7)
+    )
+  )
+
+  (func (export "as-return-value") (result i32)
+    (return (memory.grow (i32.const 0)))
+  )
+
+  (func (export "as-if-cond") (result i32)
+    (if (result i32) (memory.grow (i32.const 0))
+      (then (i32.const 0)) (else (i32.const 1))
+    )
+  )
+  (func (export "as-if-then") (result i32)
+    (if (result i32) (i32.const 1)
+      (then (memory.grow (i32.const 0))) (else (i32.const 0))
+    )
+  )
+  (func (export "as-if-else") (result i32)
+    (if (result i32) (i32.const 0)
+      (then (i32.const 0)) (else (memory.grow (i32.const 0)))
+    )
+  )
+
+  (func (export "as-select-first") (param i32 i32) (result i32)
+    (select (memory.grow (i32.const 0)) (local.get 0) (local.get 1))
+  )
+  (func (export "as-select-second") (param i32 i32) (result i32)
+    (select (local.get 0) (memory.grow (i32.const 0)) (local.get 1))
+  )
+  (func (export "as-select-cond") (result i32)
+    (select (i32.const 0) (i32.const 1) (memory.grow (i32.const 0)))
+  )
+
+  (func $f (param i32 i32 i32) (result i32) (i32.const -1))
+  (func (export "as-call-first") (result i32)
+    (call $f (memory.grow (i32.const 0)) (i32.const 2) (i32.const 3))
+  )
+  (func (export "as-call-mid") (result i32)
+    (call $f (i32.const 1) (memory.grow (i32.const 0)) (i32.const 3))
+  )
+  (func (export "as-call-last") (result i32)
+    (call $f (i32.const 1) (i32.const 2) (memory.grow (i32.const 0)))
+  )
+
+  (type $sig (func (param i32 i32 i32) (result i32)))
+  (table funcref (elem $f))
+  (func (export "as-call_indirect-first") (result i32)
+    (call_indirect (type $sig)
+      (memory.grow (i32.const 0)) (i32.const 2) (i32.const 3) (i32.const 0)
+    )
+  )
+  (func (export "as-call_indirect-mid") (result i32)
+    (call_indirect (type $sig)
+      (i32.const 1) (memory.grow (i32.const 0)) (i32.const 3) (i32.const 0)
+    )
+  )
+  (func (export "as-call_indirect-last") (result i32)
+    (call_indirect (type $sig)
+      (i32.const 1) (i32.const 2) (memory.grow (i32.const 0)) (i32.const 0)
+    )
+  )
+  (func (export "as-call_indirect-index") (result i32)
+    (call_indirect (type $sig)
+      (i32.const 1) (i32.const 2) (i32.const 3) (memory.grow (i32.const 0))
+    )
+  )
+
+  (func (export "as-local.set-value") (local i32)
+    (local.set 0 (memory.grow (i32.const 0)))
+  )
+  (func (export "as-local.tee-value") (result i32) (local i32)
+    (local.tee 0 (memory.grow (i32.const 0)))
+  )
+  (global $g (mut i32) (i32.const 0))
+  (func (export "as-global.set-value") (local i32)
+    (global.set $g (memory.grow (i32.const 0)))
+  )
+
+  (func (export "as-unary-operand") (result i32)
+    (i32.clz (memory.grow (i32.const 0)))
+  )
+
+  (func (export "as-binary-left") (result i32)
+    (i32.add (memory.grow (i32.const 0)) (i32.const 10))
+  )
+  (func (export "as-binary-right") (result i32)
+    (i32.sub (i32.const 10) (memory.grow (i32.const 0)))
+  )
+
+  (func (export "as-test-operand") (result i32)
+    (i32.eqz (memory.grow (i32.const 0)))
+  )
+
+  (func (export "as-compare-left") (result i32)
+    (i32.le_s (memory.grow (i32.const 0)) (i32.const 10))
+  )
+  (func (export "as-compare-right") (result i32)
+    (i32.ne (i32.const 10) (memory.grow (i32.const 0)))
+  )
+
+  (func (export "as-memory.grow-size") (result i32)
+    (memory.grow (memory.grow (i32.const 0)))
+  )
+)
+
+(assert_return (invoke "as-br-value") (i32.const 1))
+
+(assert_return (invoke "as-br_if-cond"))
+(assert_return (invoke "as-br_if-value") (i32.const 1))
+(assert_return (invoke "as-br_if-value-cond") (i32.const 6))
+
+(assert_return (invoke "as-br_table-index"))
+(assert_return (invoke "as-br_table-value") (i32.const 1))
+(assert_return (invoke "as-br_table-value-index") (i32.const 6))
+
+(assert_return (invoke "as-return-value") (i32.const 1))
+
+(assert_return (invoke "as-if-cond") (i32.const 0))
+(assert_return (invoke "as-if-then") (i32.const 1))
+(assert_return (invoke "as-if-else") (i32.const 1))
+
+(assert_return (invoke "as-select-first" (i32.const 0) (i32.const 1)) (i32.const 1))
+(assert_return (invoke "as-select-second" (i32.const 0) (i32.const 0)) (i32.const 1))
+(assert_return (invoke "as-select-cond") (i32.const 0))
+
+(assert_return (invoke "as-call-first") (i32.const -1))
+(assert_return (invoke "as-call-mid") (i32.const -1))
+(assert_return (invoke "as-call-last") (i32.const -1))
+
+(assert_return (invoke "as-call_indirect-first") (i32.const -1))
+(assert_return (invoke "as-call_indirect-mid") (i32.const -1))
+(assert_return (invoke "as-call_indirect-last") (i32.const -1))
+(assert_trap (invoke "as-call_indirect-index") "undefined element")
+
+(assert_return (invoke "as-local.set-value"))
+(assert_return (invoke "as-local.tee-value") (i32.const 1))
+(assert_return (invoke "as-global.set-value"))
+
+(assert_return (invoke "as-unary-operand") (i32.const 31))
+
+(assert_return (invoke "as-binary-left") (i32.const 11))
+(assert_return (invoke "as-binary-right") (i32.const 9))
+
+(assert_return (invoke "as-test-operand") (i32.const 0))
+
+(assert_return (invoke "as-compare-left") (i32.const 1))
+(assert_return (invoke "as-compare-right") (i32.const 1))
+
+(assert_return (invoke "as-memory.grow-size") (i32.const 1))
diff --git a/tests/misc_testsuite/winch/memory_init.wast b/tests/misc_testsuite/winch/memory_init.wast
new file mode 100644
index 000000000..238412350
--- /dev/null
+++ b/tests/misc_testsuite/winch/memory_init.wast
@@ -0,0 +1,742 @@
+(module
+  (memory (export "memory0") 1 1)
+  (data (i32.const 2) "\03\01\04\01")
+  (data "\02\07\01\08")
+  (data (i32.const 12) "\07\05\02\03\06")
+  (data "\05\09\02\07\06")
+  (func (export "test")
+    (nop))
+)
+
+(invoke "test")
+
+(module
+  (memory (export "memory0") 1 1)
+  (data (i32.const 2) "\03\01\04\01")
+  (data "\02\07\01\08")
+  (data (i32.const 12) "\07\05\02\03\06")
+  (data "\05\09\02\07\06")
+  (func (export "test")
+    (memory.init 1 (i32.const 7) (i32.const 0) (i32.const 4)))
+)
+
+(invoke "test")
+
+(module
+  (memory (export "memory0") 1 1)
+  (data (i32.const 2) "\03\01\04\01")
+  (data "\02\07\01\08")
+  (data (i32.const 12) "\07\05\02\03\06")
+  (data "\05\09\02\07\06")
+  (func (export "test")
+    (memory.init 3 (i32.const 15) (i32.const 1) (i32.const 3)))
+)
+
+(invoke "test")
+
+(module
+  (memory (export "memory0") 1 1)
+  (data (i32.const 2) "\03\01\04\01")
+  (data "\02\07\01\08")
+  (data (i32.const 12) "\07\05\02\03\06")
+  (data "\05\09\02\07\06")
+  (func (export "test")
+    (memory.init 1 (i32.const 7) (i32.const 0) (i32.const 4))
+    (data.drop 1)
+    (memory.init 3 (i32.const 15) (i32.const 1) (i32.const 3))
+    (data.drop 3)
+    (memory.copy (i32.const 20) (i32.const 15) (i32.const 5))
+    (memory.copy (i32.const 21) (i32.const 29) (i32.const 1))
+    (memory.copy (i32.const 24) (i32.const 10) (i32.const 1))
+    (memory.copy (i32.const 13) (i32.const 11) (i32.const 4))
+    (memory.copy (i32.const 19) (i32.const 20) (i32.const 5)))
+)
+
+(invoke "test")
+
+
+(module
+  (memory 1)
+    (data "\37")
+  (func (export "test")
+    (data.drop 0)
+    (data.drop 0)))
+(invoke "test")
+
+(module
+  (memory 1)
+    (data "\37")
+  (func (export "test")
+    (data.drop 0)
+    (memory.init 0 (i32.const 1234) (i32.const 1) (i32.const 1))))
+(assert_trap (invoke "test") "out of bounds memory access")
+
+(module
+   (memory 1)
+   (data (i32.const 0) "\37")
+   (func (export "test")
+     (memory.init 0 (i32.const 1234) (i32.const 1) (i32.const 1))))
+(assert_trap (invoke "test") "out of bounds memory access")
+
+(assert_invalid
+  (module
+    (func (export "test")
+      (memory.init 1 (i32.const 1234) (i32.const 1) (i32.const 1))))
+  "unknown memory 0")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 1 (i32.const 1234) (i32.const 1) (i32.const 1))))
+  "unknown data segment 1")
+
+(module
+  (memory 1)
+    (data "\37")
+  (func (export "test")
+    (memory.init 0 (i32.const 1) (i32.const 0) (i32.const 1))
+    (memory.init 0 (i32.const 1) (i32.const 0) (i32.const 1))))
+(invoke "test")
+
+(module
+  (memory 1)
+    (data "\37")
+  (func (export "test")
+    (memory.init 0 (i32.const 1234) (i32.const 0) (i32.const 5))))
+(assert_trap (invoke "test") "out of bounds memory access")
+
+(module
+  (memory 1)
+    (data "\37")
+  (func (export "test")
+    (memory.init 0 (i32.const 1234) (i32.const 2) (i32.const 3))))
+(assert_trap (invoke "test") "out of bounds memory access")
+
+(module
+  (memory 1)
+    (data "\37")
+  (func (export "test")
+    (memory.init 0 (i32.const 0xFFFE) (i32.const 1) (i32.const 3))))
+(assert_trap (invoke "test") "out of bounds memory access")
+
+(module
+  (memory 1)
+    (data "\37")
+  (func (export "test")
+    (memory.init 0 (i32.const 1234) (i32.const 4) (i32.const 0))))
+(assert_trap (invoke "test") "out of bounds memory access")
+
+(module
+  (memory 1)
+    (data "\37")
+  (func (export "test")
+    (memory.init 0 (i32.const 1234) (i32.const 1) (i32.const 0))))
+(invoke "test")
+
+(module
+  (memory 1)
+    (data "\37")
+  (func (export "test")
+    (memory.init 0 (i32.const 0x10001) (i32.const 0) (i32.const 0))))
+(assert_trap (invoke "test") "out of bounds memory access")
+
+(module
+  (memory 1)
+    (data "\37")
+  (func (export "test")
+    (memory.init 0 (i32.const 0x10000) (i32.const 0) (i32.const 0))))
+(invoke "test")
+
+(module
+  (memory 1)
+    (data "\37")
+  (func (export "test")
+    (memory.init 0 (i32.const 0x10000) (i32.const 1) (i32.const 0))))
+(invoke "test")
+
+(module
+  (memory 1)
+    (data "\37")
+  (func (export "test")
+    (memory.init 0 (i32.const 0x10001) (i32.const 4) (i32.const 0))))
+(assert_trap (invoke "test") "out of bounds memory access")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (i32.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (i32.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (i32.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (f32.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (f32.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (f32.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (f32.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (i64.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (i64.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (i64.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (i64.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (f64.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (f64.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (f64.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i32.const 1) (f64.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (i32.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (i32.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (i32.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (i32.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (f32.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (f32.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (f32.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (f32.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (i64.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (i64.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (i64.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (i64.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (f64.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (f64.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (f64.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f32.const 1) (f64.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (i32.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (i32.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (i32.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (i32.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (f32.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (f32.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (f32.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (f32.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (i64.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (i64.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (i64.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (i64.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (f64.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (f64.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (f64.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (i64.const 1) (f64.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (i32.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (i32.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (i32.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (i32.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (f32.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (f32.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (f32.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (f32.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (i64.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (i64.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (i64.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (i64.const 1) (f64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (f64.const 1) (i32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (f64.const 1) (f32.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (f64.const 1) (i64.const 1))))
+  "type mismatch")
+
+(assert_invalid
+  (module
+    (memory 1)
+    (data "\37")
+    (func (export "test")
+      (memory.init 0 (f64.const 1) (f64.const 1) (f64.const 1))))
+  "type mismatch")
+
+(module
+  (memory 1 1 )
+  (data "\42\42\42\42\42\42\42\42\42\42\42\42\42\42\42\42")
+   
+  (func (export "run") (param $offs i32) (param $len i32)
+    (memory.init 0 (local.get $offs) (i32.const 0) (local.get $len))))
+
+(assert_trap (invoke "run" (i32.const 65528) (i32.const 16))
+              "out of bounds memory access")
+
+(module
+  (memory 1 1 )
+  (data "\42\42\42\42\42\42\42\42\42\42\42\42\42\42\42\42")
+   
+  (func (export "run") (param $offs i32) (param $len i32)
+    (memory.init 0 (local.get $offs) (i32.const 0) (local.get $len))))
+
+(assert_trap (invoke "run" (i32.const 65527) (i32.const 16))
+              "out of bounds memory access")
+(module
+  (memory 1 1 )
+  (data "\42\42\42\42\42\42\42\42\42\42\42\42\42\42\42\42")
+   
+  (func (export "run") (param $offs i32) (param $len i32)
+    (memory.init 0 (local.get $offs) (i32.const 0) (local.get $len))))
+
+(assert_trap (invoke "run" (i32.const 65472) (i32.const 30))
+              "out of bounds memory access")
+
+(module
+  (memory 1 1 )
+  (data "\42\42\42\42\42\42\42\42\42\42\42\42\42\42\42\42")
+   
+  (func (export "run") (param $offs i32) (param $len i32)
+    (memory.init 0 (local.get $offs) (i32.const 0) (local.get $len))))
+
+(assert_trap (invoke "run" (i32.const 65473) (i32.const 31))
+              "out of bounds memory access")
+(module
+  (memory 1  )
+  (data "\42\42\42\42\42\42\42\42\42\42\42\42\42\42\42\42")
+   
+
+  (func (export "run") (param $offs i32) (param $len i32)
+    (memory.init 0 (local.get $offs) (i32.const 0) (local.get $len))))
+
+(assert_trap (invoke "run" (i32.const 65528) (i32.const 4294967040))
+              "out of bounds memory access")
+
+(module
+  (memory 1  )
+  (data "\42\42\42\42\42\42\42\42\42\42\42\42\42\42\42\42")
+   
+  (func (export "run") (param $offs i32) (param $len i32)
+    (memory.init 0 (local.get $offs) (i32.const 0) (local.get $len))))
+
+(assert_trap (invoke "run" (i32.const 0) (i32.const 4294967292))
+              "out of bounds memory access")
+
+(module
+  (memory 1)
+  ;; 65 data segments. 64 is the smallest positive number that is encoded
+  ;; differently as a signed LEB.
+  (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
+  (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
+  (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
+  (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
+  (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
+  (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
+  (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
+  (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
+  (data "")
+  (func (memory.init 64 (i32.const 0) (i32.const 0) (i32.const 0))))
diff --git a/tests/misc_testsuite/winch/memory_size.wast b/tests/misc_testsuite/winch/memory_size.wast
new file mode 100644
index 000000000..239e66d8f
--- /dev/null
+++ b/tests/misc_testsuite/winch/memory_size.wast
@@ -0,0 +1,85 @@
+(module
+  (memory 0)
+  (func (export "size") (result i32) (memory.size))
+  (func (export "grow") (param $sz i32) (drop (memory.grow (local.get $sz))))
+)
+
+(assert_return (invoke "size") (i32.const 0))
+(assert_return (invoke "grow" (i32.const 1)))
+(assert_return (invoke "size") (i32.const 1))
+(assert_return (invoke "grow" (i32.const 4)))
+(assert_return (invoke "size") (i32.const 5))
+(assert_return (invoke "grow" (i32.const 0)))
+(assert_return (invoke "size") (i32.const 5))
+
+(module
+  (memory 1)
+  (func (export "size") (result i32) (memory.size))
+  (func (export "grow") (param $sz i32) (drop (memory.grow (local.get $sz))))
+)
+
+(assert_return (invoke "size") (i32.const 1))
+(assert_return (invoke "grow" (i32.const 1)))
+(assert_return (invoke "size") (i32.const 2))
+(assert_return (invoke "grow" (i32.const 4)))
+(assert_return (invoke "size") (i32.const 6))
+(assert_return (invoke "grow" (i32.const 0)))
+(assert_return (invoke "size") (i32.const 6))
+
+(module
+  (memory 0 2)
+  (func (export "size") (result i32) (memory.size))
+  (func (export "grow") (param $sz i32) (drop (memory.grow (local.get $sz))))
+)
+
+(assert_return (invoke "size") (i32.const 0))
+(assert_return (invoke "grow" (i32.const 3)))
+(assert_return (invoke "size") (i32.const 0))
+(assert_return (invoke "grow" (i32.const 1)))
+(assert_return (invoke "size") (i32.const 1))
+(assert_return (invoke "grow" (i32.const 0)))
+(assert_return (invoke "size") (i32.const 1))
+(assert_return (invoke "grow" (i32.const 4)))
+(assert_return (invoke "size") (i32.const 1))
+(assert_return (invoke "grow" (i32.const 1)))
+(assert_return (invoke "size") (i32.const 2))
+
+(module
+  (memory 3 8)
+  (func (export "size") (result i32) (memory.size))
+  (func (export "grow") (param $sz i32) (drop (memory.grow (local.get $sz))))
+)
+
+(assert_return (invoke "size") (i32.const 3))
+(assert_return (invoke "grow" (i32.const 1)))
+(assert_return (invoke "size") (i32.const 4))
+(assert_return (invoke "grow" (i32.const 3)))
+(assert_return (invoke "size") (i32.const 7))
+(assert_return (invoke "grow" (i32.const 0)))
+(assert_return (invoke "size") (i32.const 7))
+(assert_return (invoke "grow" (i32.const 2)))
+(assert_return (invoke "size") (i32.const 7))
+(assert_return (invoke "grow" (i32.const 1)))
+(assert_return (invoke "size") (i32.const 8))
+
+
+;; Type errors
+
+(assert_invalid
+  (module
+    (memory 1)
+    (func $type-result-i32-vs-empty
+      (memory.size)
+    )
+  )
+  "type mismatch"
+)
+(assert_invalid
+  (module
+    (memory 1)
+    (func $type-result-i32-vs-f32 (result f32)
+      (memory.size)
+    )
+  )
+  "type mismatch"
+)