From 7f3ffbc8c22d0084987966b0496a63ce4d6278d5 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Thu, 28 Oct 2021 10:58:16 -0700
Subject: [PATCH 01/17] std: Get the standard library compiling for wasm64

This commit goes through and updates various `#[cfg]` as appropriate to
get the wasm64-unknown-unknown target behaving similarly to the
wasm32-unknown-unknown target. Most of this is just updating various
conditions for `target_arch = "wasm32"` to also account for `target_arch
= "wasm64"` where appropriate. This commit also lists `wasm64` as an
allow-listed architecture to not have the `restricted_std` feature
enabled, enabling experimentation with `-Z build-std` externally.

The main goal of this commit is to enable playing around with
`wasm64-unknown-unknown` externally via `-Z build-std` in a way that's
similar to the `wasm32-unknown-unknown` target. These targets are
effectively the same and only differ in their pointer size, but wasm64
is much newer and has much less ecosystem/library support so it'll still
take time to get wasm64 fully-fledged.
---
 .../src/spec/wasm64_unknown_unknown.rs        |  9 ++++----
 library/core/src/ffi.rs                       |  6 +++++
 library/panic_abort/src/lib.rs                |  3 ++-
 library/panic_unwind/src/dummy.rs             |  4 ++--
 library/panic_unwind/src/lib.rs               |  1 +
 library/std/Cargo.toml                        |  2 +-
 library/std/build.rs                          |  1 +
 library/std/src/sys/common/alloc.rs           |  3 ++-
 library/std/src/sys/mod.rs                    |  2 +-
 library/std/src/sys/wasm/alloc.rs             |  4 ++--
 library/std/src/sys_common/mod.rs             |  1 +
 library/std/src/thread/local.rs               | 22 ++++++++++++-------
 library/std/src/thread/mod.rs                 |  5 ++++-
 13 files changed, 41 insertions(+), 22 deletions(-)

diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
index fb6526c0e72..7eacbb43640 100644
--- a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
@@ -23,11 +23,10 @@ pub fn target() -> Target {
     // For now this target just never has an entry symbol no matter the output
     // type, so unconditionally pass this.
     clang_args.push("-Wl,--no-entry".to_string());
-    options
-        .pre_link_args
-        .get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm))
-        .unwrap()
-        .push("--no-entry".to_string());
+
+    let lld_args = options.pre_link_args.get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm)).unwrap();
+    lld_args.push("--no-entry".to_string());
+    lld_args.push("-mwasm64".to_string());
 
     Target {
         llvm_target: "wasm64-unknown-unknown".to_string(),
diff --git a/library/core/src/ffi.rs b/library/core/src/ffi.rs
index b208ddd4b27..ea3de680afe 100644
--- a/library/core/src/ffi.rs
+++ b/library/core/src/ffi.rs
@@ -63,6 +63,7 @@ impl fmt::Debug for c_void {
     all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
     all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
     target_arch = "wasm32",
+    target_arch = "wasm64",
     target_arch = "asmjs",
     windows
 ))]
@@ -86,6 +87,7 @@ pub struct VaListImpl<'f> {
     all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
     all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
     target_arch = "wasm32",
+    target_arch = "wasm64",
     target_arch = "asmjs",
     windows
 ))]
@@ -186,6 +188,7 @@ pub struct VaList<'a, 'f: 'a> {
         ),
         all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
         target_arch = "wasm32",
+        target_arch = "wasm64",
         target_arch = "asmjs",
         windows
     ))]
@@ -195,6 +198,7 @@ pub struct VaList<'a, 'f: 'a> {
         any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
         any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
         not(target_arch = "wasm32"),
+        not(target_arch = "wasm64"),
         not(target_arch = "asmjs"),
         not(windows)
     ))]
@@ -207,6 +211,7 @@ pub struct VaList<'a, 'f: 'a> {
     all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
     all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
     target_arch = "wasm32",
+    target_arch = "wasm64",
     target_arch = "asmjs",
     windows
 ))]
@@ -228,6 +233,7 @@ impl<'f> VaListImpl<'f> {
     any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
     any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
     not(target_arch = "wasm32"),
+    not(target_arch = "wasm64"),
     not(target_arch = "asmjs"),
     not(windows)
 ))]
diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs
index ac75ce7f221..d31df0da364 100644
--- a/library/panic_abort/src/lib.rs
+++ b/library/panic_abort/src/lib.rs
@@ -117,7 +117,8 @@ pub unsafe extern "C-unwind" fn __rust_start_panic(_payload: *mut &mut dyn BoxMe
 pub mod personalities {
     #[rustc_std_internal_symbol]
     #[cfg(not(any(
-        all(target_arch = "wasm32", not(target_os = "emscripten"),),
+        all(target_arch = "wasm32", not(target_os = "emscripten")),
+        all(target_arch = "wasm64", not(target_os = "emscripten")),
         all(target_os = "windows", target_env = "gnu", target_arch = "x86_64",),
     )))]
     pub extern "C" fn rust_eh_personality() {}
diff --git a/library/panic_unwind/src/dummy.rs b/library/panic_unwind/src/dummy.rs
index 4667ede2baa..a4bcd216c60 100644
--- a/library/panic_unwind/src/dummy.rs
+++ b/library/panic_unwind/src/dummy.rs
@@ -1,6 +1,6 @@
-//! Unwinding for *wasm32* target.
+//! Unwinding for unsupported target.
 //!
-//! Right now we don't support this, so this is just stubs.
+//! Stubs that simply abort for targets that don't support unwinding otherwise.
 
 use alloc::boxed::Box;
 use core::any::Any;
diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs
index b5d0ca2572c..4815249f7d5 100644
--- a/library/panic_unwind/src/lib.rs
+++ b/library/panic_unwind/src/lib.rs
@@ -57,6 +57,7 @@ cfg_if::cfg_if! {
     } else {
         // Targets that don't support unwinding.
         // - arch=wasm32
+        // - arch=wasm64
         // - os=none ("bare metal" targets)
         // - os=uefi
         // - os=espidf
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 248ecdf4bef..85658bf9e3c 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -35,7 +35,7 @@ features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive']
 [dev-dependencies]
 rand = "0.7"
 
-[target.'cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
+[target.'cfg(any(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
 dlmalloc = { version = "0.2.1", features = ['rustc-dep-of-std'] }
 
 [target.x86_64-fortanix-unknown-sgx.dependencies]
diff --git a/library/std/build.rs b/library/std/build.rs
index cc7184d57f1..43168e77296 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -25,6 +25,7 @@ fn main() {
         || target.contains("haiku")
         || target.contains("vxworks")
         || target.contains("wasm32")
+        || target.contains("wasm64")
         || target.contains("asmjs")
         || target.contains("espidf")
         || target.contains("solid")
diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs
index 576667c0173..9665d1fa892 100644
--- a/library/std/src/sys/common/alloc.rs
+++ b/library/std/src/sys/common/alloc.rs
@@ -24,7 +24,8 @@ pub const MIN_ALIGN: usize = 8;
     target_arch = "mips64",
     target_arch = "s390x",
     target_arch = "sparc64",
-    target_arch = "riscv64"
+    target_arch = "riscv64",
+    target_arch = "wasm64",
 )))]
 pub const MIN_ALIGN: usize = 16;
 
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index 8b8be6ebc2f..38f45fef918 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -40,7 +40,7 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_os = "wasi")] {
         mod wasi;
         pub use self::wasi::*;
-    } else if #[cfg(target_arch = "wasm32")] {
+    } else if #[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))] {
         mod wasm;
         pub use self::wasm::*;
     } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
diff --git a/library/std/src/sys/wasm/alloc.rs b/library/std/src/sys/wasm/alloc.rs
index ef0ca3dd478..bf5dc0273c0 100644
--- a/library/std/src/sys/wasm/alloc.rs
+++ b/library/std/src/sys/wasm/alloc.rs
@@ -1,8 +1,8 @@
-//! This is an implementation of a global allocator on the wasm32 platform when
+//! This is an implementation of a global allocator on the wasm platform when
 //! emscripten is not in use. In that situation there's no actual runtime for us
 //! to lean on for allocation, so instead we provide our own!
 //!
-//! The wasm32 instruction set has two instructions for getting the current
+//! The wasm instruction set has two instructions for getting the current
 //! amount of memory and growing the amount of memory. These instructions are the
 //! foundation on which we're able to build an allocator, so we do so! Note that
 //! the instructions are also pretty "global" and this is the "global" allocator
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 5a5913ebd79..0f2a8cd0012 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -41,6 +41,7 @@ cfg_if::cfg_if! {
                  target_os = "hermit",
                  feature = "restricted-std",
                  all(target_arch = "wasm32", not(target_os = "emscripten")),
+                 all(target_arch = "wasm64", not(target_os = "emscripten")),
                  all(target_vendor = "fortanix", target_env = "sgx")))] {
         pub use crate::sys::net;
     } else {
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index c53290ec0c7..37f9cc40be6 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -172,7 +172,7 @@ macro_rules! __thread_local_inner {
             //
             // FIXME(#84224) this should come after the `target_thread_local`
             // block.
-            #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
+            #[cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics")))]
             {
                 static mut VAL: $t = $init;
                 Some(&VAL)
@@ -181,7 +181,10 @@ macro_rules! __thread_local_inner {
             // If the platform has support for `#[thread_local]`, use it.
             #[cfg(all(
                 target_thread_local,
-                not(all(target_arch = "wasm32", not(target_feature = "atomics"))),
+                not(all(
+                    any(target_arch = "wasm32", target_arch = "wasm64"),
+                    not(target_feature = "atomics"),
+                )),
             ))]
             {
                 // If a dtor isn't needed we can do something "very raw" and
@@ -238,7 +241,10 @@ macro_rules! __thread_local_inner {
             // same implementation as below for os thread locals.
             #[cfg(all(
                 not(target_thread_local),
-                not(all(target_arch = "wasm32", not(target_feature = "atomics"))),
+                not(all(
+                    any(target_arch = "wasm32", target_arch = "wasm64"),
+                    not(target_feature = "atomics"),
+                )),
             ))]
             {
                 #[inline]
@@ -285,21 +291,21 @@ macro_rules! __thread_local_inner {
             // The issue of "should enable on Windows sometimes" is #84933
             #[cfg_attr(not(windows), inline)]
             unsafe fn __getit() -> $crate::option::Option<&'static $t> {
-                #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
+                #[cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics")))]
                 static __KEY: $crate::thread::__StaticLocalKeyInner<$t> =
                     $crate::thread::__StaticLocalKeyInner::new();
 
                 #[thread_local]
                 #[cfg(all(
                     target_thread_local,
-                    not(all(target_arch = "wasm32", not(target_feature = "atomics"))),
+                    not(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics"))),
                 ))]
                 static __KEY: $crate::thread::__FastLocalKeyInner<$t> =
                     $crate::thread::__FastLocalKeyInner::new();
 
                 #[cfg(all(
                     not(target_thread_local),
-                    not(all(target_arch = "wasm32", not(target_feature = "atomics"))),
+                    not(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics"))),
                 ))]
                 static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
                     $crate::thread::__OsLocalKeyInner::new();
@@ -479,10 +485,10 @@ mod lazy {
     }
 }
 
-/// On some platforms like wasm32 there's no threads, so no need to generate
+/// On some platforms like wasm there's no threads, so no need to generate
 /// thread locals and we can instead just use plain statics!
 #[doc(hidden)]
-#[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
+#[cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics")))]
 pub mod statik {
     use super::lazy::LazyKeyInner;
     use crate::fmt;
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 2a155ce3117..41f7bf55f22 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -200,7 +200,10 @@ pub use self::local::fast::Key as __FastLocalKeyInner;
 #[doc(hidden)]
 pub use self::local::os::Key as __OsLocalKeyInner;
 #[unstable(feature = "libstd_thread_internals", issue = "none")]
-#[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
+#[cfg(all(
+    any(target_arch = "wasm32", target_arch = "wasm64"),
+    not(target_feature = "atomics")
+))]
 #[doc(hidden)]
 pub use self::local::statik::Key as __StaticLocalKeyInner;
 

From cfb2f98e9e0bfbad2078b6632c1456c528824088 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Thu, 28 Oct 2021 11:20:46 -0700
Subject: [PATCH 02/17] Enable WebAssembly features by default on wasm64

These are all stable as-of-now in the WebAssembly specification so any
engine which implements wasm64 will surely implement these features as
well.
---
 compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
index 7eacbb43640..6b7dfbb87d2 100644
--- a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
@@ -28,6 +28,11 @@ pub fn target() -> Target {
     lld_args.push("--no-entry".to_string());
     lld_args.push("-mwasm64".to_string());
 
+    // Any engine that implements wasm64 will surely implement the rest of these
+    // features since they were all merged into the official spec by the time
+    // wasm64 was designed.
+    options.features = "+bulk-memory,+mutable-globals,+sign-ext,+nontrapping-fptoint".to_string();
+
     Target {
         llvm_target: "wasm64-unknown-unknown".to_string(),
         pointer_width: 64,

From 971638824fd859eb28dbee069ad109fc80e3e5c5 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Thu, 28 Oct 2021 16:28:21 -0700
Subject: [PATCH 03/17] Use `target_family = "wasm"`

---
 library/core/src/ffi.rs           | 18 ++++++------------
 library/panic_abort/src/lib.rs    |  3 +--
 library/std/Cargo.toml            |  2 +-
 library/std/src/sys/mod.rs        |  2 +-
 library/std/src/sys_common/mod.rs |  3 +--
 library/std/src/thread/local.rs   | 20 +++++++-------------
 library/std/src/thread/mod.rs     |  5 +----
 7 files changed, 18 insertions(+), 35 deletions(-)

diff --git a/library/core/src/ffi.rs b/library/core/src/ffi.rs
index ea3de680afe..9c4cf89b6bc 100644
--- a/library/core/src/ffi.rs
+++ b/library/core/src/ffi.rs
@@ -62,8 +62,7 @@ impl fmt::Debug for c_void {
 #[cfg(any(
     all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
     all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
-    target_arch = "wasm32",
-    target_arch = "wasm64",
+    target_family = "wasm",
     target_arch = "asmjs",
     windows
 ))]
@@ -86,8 +85,7 @@ pub struct VaListImpl<'f> {
 #[cfg(any(
     all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
     all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
-    target_arch = "wasm32",
-    target_arch = "wasm64",
+    target_family = "wasm",
     target_arch = "asmjs",
     windows
 ))]
@@ -187,8 +185,7 @@ pub struct VaList<'a, 'f: 'a> {
             not(target_arch = "x86_64")
         ),
         all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
-        target_arch = "wasm32",
-        target_arch = "wasm64",
+        target_family = "wasm",
         target_arch = "asmjs",
         windows
     ))]
@@ -197,8 +194,7 @@ pub struct VaList<'a, 'f: 'a> {
     #[cfg(all(
         any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
         any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
-        not(target_arch = "wasm32"),
-        not(target_arch = "wasm64"),
+        not(target_family = "wasm"),
         not(target_arch = "asmjs"),
         not(windows)
     ))]
@@ -210,8 +206,7 @@ pub struct VaList<'a, 'f: 'a> {
 #[cfg(any(
     all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
     all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
-    target_arch = "wasm32",
-    target_arch = "wasm64",
+    target_family = "wasm",
     target_arch = "asmjs",
     windows
 ))]
@@ -232,8 +227,7 @@ impl<'f> VaListImpl<'f> {
 #[cfg(all(
     any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
     any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
-    not(target_arch = "wasm32"),
-    not(target_arch = "wasm64"),
+    not(target_family = "wasm"),
     not(target_arch = "asmjs"),
     not(windows)
 ))]
diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs
index d31df0da364..dec5e0b2123 100644
--- a/library/panic_abort/src/lib.rs
+++ b/library/panic_abort/src/lib.rs
@@ -117,8 +117,7 @@ pub unsafe extern "C-unwind" fn __rust_start_panic(_payload: *mut &mut dyn BoxMe
 pub mod personalities {
     #[rustc_std_internal_symbol]
     #[cfg(not(any(
-        all(target_arch = "wasm32", not(target_os = "emscripten")),
-        all(target_arch = "wasm64", not(target_os = "emscripten")),
+        all(target_family = "wasm", not(target_os = "emscripten")),
         all(target_os = "windows", target_env = "gnu", target_arch = "x86_64",),
     )))]
     pub extern "C" fn rust_eh_personality() {}
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 85658bf9e3c..752ab185b8e 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -35,7 +35,7 @@ features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive']
 [dev-dependencies]
 rand = "0.7"
 
-[target.'cfg(any(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
+[target.'cfg(any(all(target_family = "wasm", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
 dlmalloc = { version = "0.2.1", features = ['rustc-dep-of-std'] }
 
 [target.x86_64-fortanix-unknown-sgx.dependencies]
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index 38f45fef918..167c918c94c 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -40,7 +40,7 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_os = "wasi")] {
         mod wasi;
         pub use self::wasi::*;
-    } else if #[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))] {
+    } else if #[cfg(target_family = "wasm")] {
         mod wasm;
         pub use self::wasm::*;
     } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 0f2a8cd0012..804727fbc54 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -40,8 +40,7 @@ cfg_if::cfg_if! {
     if #[cfg(any(target_os = "l4re",
                  target_os = "hermit",
                  feature = "restricted-std",
-                 all(target_arch = "wasm32", not(target_os = "emscripten")),
-                 all(target_arch = "wasm64", not(target_os = "emscripten")),
+                 all(target_family = "wasm", not(target_os = "emscripten")),
                  all(target_vendor = "fortanix", target_env = "sgx")))] {
         pub use crate::sys::net;
     } else {
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index 37f9cc40be6..da297c92017 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -172,7 +172,7 @@ macro_rules! __thread_local_inner {
             //
             // FIXME(#84224) this should come after the `target_thread_local`
             // block.
-            #[cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics")))]
+            #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
             {
                 static mut VAL: $t = $init;
                 Some(&VAL)
@@ -181,10 +181,7 @@ macro_rules! __thread_local_inner {
             // If the platform has support for `#[thread_local]`, use it.
             #[cfg(all(
                 target_thread_local,
-                not(all(
-                    any(target_arch = "wasm32", target_arch = "wasm64"),
-                    not(target_feature = "atomics"),
-                )),
+                not(all(target_family = "wasm", not(target_feature = "atomics"))),
             ))]
             {
                 // If a dtor isn't needed we can do something "very raw" and
@@ -241,10 +238,7 @@ macro_rules! __thread_local_inner {
             // same implementation as below for os thread locals.
             #[cfg(all(
                 not(target_thread_local),
-                not(all(
-                    any(target_arch = "wasm32", target_arch = "wasm64"),
-                    not(target_feature = "atomics"),
-                )),
+                not(all(target_family = "wasm", not(target_feature = "atomics"))),
             ))]
             {
                 #[inline]
@@ -291,21 +285,21 @@ macro_rules! __thread_local_inner {
             // The issue of "should enable on Windows sometimes" is #84933
             #[cfg_attr(not(windows), inline)]
             unsafe fn __getit() -> $crate::option::Option<&'static $t> {
-                #[cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics")))]
+                #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
                 static __KEY: $crate::thread::__StaticLocalKeyInner<$t> =
                     $crate::thread::__StaticLocalKeyInner::new();
 
                 #[thread_local]
                 #[cfg(all(
                     target_thread_local,
-                    not(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics"))),
+                    not(all(target_family = "wasm", not(target_feature = "atomics"))),
                 ))]
                 static __KEY: $crate::thread::__FastLocalKeyInner<$t> =
                     $crate::thread::__FastLocalKeyInner::new();
 
                 #[cfg(all(
                     not(target_thread_local),
-                    not(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics"))),
+                    not(all(target_family = "wasm", not(target_feature = "atomics"))),
                 ))]
                 static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
                     $crate::thread::__OsLocalKeyInner::new();
@@ -488,7 +482,7 @@ mod lazy {
 /// On some platforms like wasm there's no threads, so no need to generate
 /// thread locals and we can instead just use plain statics!
 #[doc(hidden)]
-#[cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics")))]
+#[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
 pub mod statik {
     use super::lazy::LazyKeyInner;
     use crate::fmt;
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 41f7bf55f22..39b53b51bfa 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -200,10 +200,7 @@ pub use self::local::fast::Key as __FastLocalKeyInner;
 #[doc(hidden)]
 pub use self::local::os::Key as __OsLocalKeyInner;
 #[unstable(feature = "libstd_thread_internals", issue = "none")]
-#[cfg(all(
-    any(target_arch = "wasm32", target_arch = "wasm64"),
-    not(target_feature = "atomics")
-))]
+#[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
 #[doc(hidden)]
 pub use self::local::statik::Key as __StaticLocalKeyInner;
 

From f738abe63b6c351e0ba523a01b05d04fead8acff Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Thu, 28 Oct 2021 16:29:23 -0700
Subject: [PATCH 04/17] Update platform support docs

---
 src/doc/rustc/src/platform-support.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 6b0c336b3c7..b749d7f0891 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -276,7 +276,7 @@ target | std | host | notes
 `thumbv7a-pc-windows-msvc` | ? |  |
 `thumbv7a-uwp-windows-msvc` | ✓ |  |
 `thumbv7neon-unknown-linux-musleabihf` | ? |  | Thumb2-mode ARMv7a Linux with NEON, MUSL
-`wasm64-unknown-unknown` | * |  | WebAssembly
+`wasm64-unknown-unknown` | ? |  | WebAssembly
 `x86_64-apple-ios-macabi` | ✓ |  | Apple Catalyst on x86_64
 `x86_64-apple-tvos` | * | | x86 64-bit tvOS
 `x86_64-pc-windows-msvc` | ✓ |  | 64-bit Windows XP support

From caa9e4a2d0feaee53df67677a190edab95c996af Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Mon, 1 Nov 2021 07:11:05 -0700
Subject: [PATCH 05/17] Review comments

---
 library/panic_unwind/src/lib.rs   | 3 +--
 library/std/src/sys/wasm/alloc.rs | 2 +-
 library/std/src/thread/local.rs   | 2 +-
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs
index 4815249f7d5..e5753ccae2d 100644
--- a/library/panic_unwind/src/lib.rs
+++ b/library/panic_unwind/src/lib.rs
@@ -56,8 +56,7 @@ cfg_if::cfg_if! {
         mod real_imp;
     } else {
         // Targets that don't support unwinding.
-        // - arch=wasm32
-        // - arch=wasm64
+        // - family=wasm
         // - os=none ("bare metal" targets)
         // - os=uefi
         // - os=espidf
diff --git a/library/std/src/sys/wasm/alloc.rs b/library/std/src/sys/wasm/alloc.rs
index bf5dc0273c0..3223e894102 100644
--- a/library/std/src/sys/wasm/alloc.rs
+++ b/library/std/src/sys/wasm/alloc.rs
@@ -1,4 +1,4 @@
-//! This is an implementation of a global allocator on the wasm platform when
+//! This is an implementation of a global allocator on wasm targets when
 //! emscripten is not in use. In that situation there's no actual runtime for us
 //! to lean on for allocation, so instead we provide our own!
 //!
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index da297c92017..f6898d283fc 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -479,7 +479,7 @@ mod lazy {
     }
 }
 
-/// On some platforms like wasm there's no threads, so no need to generate
+/// On some targets like wasm there's no threads, so no need to generate
 /// thread locals and we can instead just use plain statics!
 #[doc(hidden)]
 #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]

From d208e1943bd94f0646dbb6fdc1a14d1973bf63a5 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Mon, 1 Nov 2021 14:16:25 -0700
Subject: [PATCH 06/17] Fix a crash with wasm64 in LLVM

This commit works around a crash in LLVM when the
`-generate-arange-section` argument is passed to LLVM. An LLVM bug is
opened for this and the code in question is also set to continue passing
this flag with LLVM 14, assuming that this is fixed by the time LLVM 14
comes out. Otherwise this should work around debuginfo crashes on LLVM
13.
---
 compiler/rustc_codegen_llvm/src/llvm_util.rs | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index c3e7e7169a9..35a3d21036a 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -75,7 +75,15 @@ unsafe fn configure_llvm(sess: &Session) {
         if sess.print_llvm_passes() {
             add("-debug-pass=Structure", false);
         }
-        if !sess.opts.debugging_opts.no_generate_arange_section {
+        if !sess.opts.debugging_opts.no_generate_arange_section
+            // FIXME: An LLVM bug [1] means that if this option is enabled for
+            // wasm64 then LLVM will crash when generating debuginfo. Assuming
+            // that this gets fixed in LLVM 14 this condition here is a
+            // workaround to work with versions of LLVM 13 and prior.
+            //
+            // [1]: https://bugs.llvm.org/show_bug.cgi?id=52376
+            && (sess.target.arch != "wasm64" || llvm_util::get_version() >= (14, 0, 0))
+        {
             add("-generate-arange-section", false);
         }
 

From d2a3c24a9582492d98652a7d88140c34e03c717e Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Mon, 1 Nov 2021 13:44:28 -0700
Subject: [PATCH 07/17] Update more rustc/libtest things for wasm64

* Add wasm64 variants for inline assembly along the same lines as wasm32
* Update a few directives in libtest to check for `target_family`
  instead of `target_arch`
* Update some rustc codegen and typechecks specialized for wasm32 to
  also work for wasm64.
---
 compiler/rustc_codegen_llvm/src/asm.rs     |  2 +-
 compiler/rustc_codegen_llvm/src/builder.rs |  4 ++--
 compiler/rustc_codegen_llvm/src/consts.rs  |  2 +-
 compiler/rustc_target/src/asm/mod.rs       | 10 +++++++---
 compiler/rustc_typeck/src/check/mod.rs     |  2 +-
 library/test/src/console.rs                |  2 +-
 library/test/src/lib.rs                    |  4 ++--
 src/bootstrap/test.rs                      |  2 +-
 8 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index f128f769580..02096f4abfa 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -320,7 +320,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
                 InlineAsmArch::Mips | InlineAsmArch::Mips64 => {}
                 InlineAsmArch::S390x => {}
                 InlineAsmArch::SpirV => {}
-                InlineAsmArch::Wasm32 => {}
+                InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {}
                 InlineAsmArch::Bpf => {}
             }
         }
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 6c74163fb49..0041a44a4d8 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -769,7 +769,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         // we like. To ensure that LLVM picks the right instruction we choose
         // the raw wasm intrinsic functions which avoid LLVM inserting all the
         // other control flow automatically.
-        if self.sess().target.arch == "wasm32" {
+        if self.sess().target.arch.starts_with("wasm32") {
             let src_ty = self.cx.val_ty(val);
             if self.cx.type_kind(src_ty) != TypeKind::Vector {
                 let float_width = self.cx.float_width(src_ty);
@@ -791,7 +791,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
     fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         // see `fptoui` above for why wasm is different here
-        if self.sess().target.arch == "wasm32" {
+        if self.sess().target.arch.starts_with("wasm") {
             let src_ty = self.cx.val_ty(val);
             if self.cx.type_kind(src_ty) != TypeKind::Vector {
                 let float_width = self.cx.float_width(src_ty);
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 1afa6f02836..cbdc76c55e4 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -490,7 +490,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
 
             // Wasm statics with custom link sections get special treatment as they
             // go into custom sections of the wasm executable.
-            if self.tcx.sess.opts.target_triple.triple().starts_with("wasm32") {
+            if self.tcx.sess.opts.target_triple.triple().starts_with("wasm") {
                 if let Some(section) = attrs.link_section {
                     let section = llvm::LLVMMDStringInContext(
                         self.llcx,
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index 99699c50df5..bff13246521 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -189,6 +189,7 @@ pub enum InlineAsmArch {
     S390x,
     SpirV,
     Wasm32,
+    Wasm64,
     Bpf,
 }
 
@@ -212,6 +213,7 @@ impl FromStr for InlineAsmArch {
             "s390x" => Ok(Self::S390x),
             "spirv" => Ok(Self::SpirV),
             "wasm32" => Ok(Self::Wasm32),
+            "wasm64" => Ok(Self::Wasm64),
             "bpf" => Ok(Self::Bpf),
             _ => Err(()),
         }
@@ -318,7 +320,7 @@ impl InlineAsmReg {
             InlineAsmArch::SpirV => {
                 Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?)
             }
-            InlineAsmArch::Wasm32 => {
+            InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
                 Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, &name)?)
             }
             InlineAsmArch::Bpf => {
@@ -529,7 +531,9 @@ impl InlineAsmRegClass {
             }
             InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(arch, name)?),
             InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?),
-            InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?),
+            InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
+                Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?)
+            }
             InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?),
         })
     }
@@ -725,7 +729,7 @@ pub fn allocatable_registers(
             spirv::fill_reg_map(arch, has_feature, target, &mut map);
             map
         }
-        InlineAsmArch::Wasm32 => {
+        InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
             let mut map = wasm::regclass_map();
             wasm::fill_reg_map(arch, has_feature, target, &mut map);
             map
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index d19e99606bc..1404a55bcaa 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -537,7 +537,7 @@ fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
 
 fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId, span: Span) {
     // Only restricted on wasm32 target for now
-    if !tcx.sess.opts.target_triple.triple().starts_with("wasm32") {
+    if !tcx.sess.opts.target_triple.triple().starts_with("wasm") {
         return;
     }
 
diff --git a/library/test/src/console.rs b/library/test/src/console.rs
index 11c5ab48ed3..9c261e8cc8e 100644
--- a/library/test/src/console.rs
+++ b/library/test/src/console.rs
@@ -284,7 +284,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
     // Prevent the usage of `Instant` in some cases:
     // - It's currently not supported for wasm targets.
     // - We disable it for miri because it's not available when isolation is enabled.
-    let is_instant_supported = !cfg!(target_arch = "wasm32") && !cfg!(miri);
+    let is_instant_supported = !cfg!(target_family = "wasm") && !cfg!(miri);
 
     let start_time = is_instant_supported.then(Instant::now);
     run_tests(opts, tests, |x| on_test_event(&x, &mut st, &mut *out))?;
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 99d951d8016..2516f3452b1 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -470,7 +470,7 @@ pub fn run_test(
 
     // Emscripten can catch panics but other wasm targets cannot
     let ignore_because_no_process_support = desc.should_panic != ShouldPanic::No
-        && cfg!(target_arch = "wasm32")
+        && cfg!(target_family = "wasm")
         && !cfg!(target_os = "emscripten");
 
     if force_ignore || desc.ignore || ignore_because_no_process_support {
@@ -519,7 +519,7 @@ pub fn run_test(
         // If the platform is single-threaded we're just going to run
         // the test synchronously, regardless of the concurrency
         // level.
-        let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_arch = "wasm32");
+        let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_family = "wasm");
         if concurrency == Concurrent::Yes && supports_threads {
             let cfg = thread::Builder::new().name(name.as_slice().to_owned());
             let mut runtest = Arc::new(Mutex::new(Some(runtest)));
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 22bf6b8a9d4..cb1b0ebf8db 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1276,7 +1276,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
         builder.ensure(native::TestHelpers { target: compiler.host });
 
         // As well as the target, except for plain wasm32, which can't build it
-        if !target.contains("wasm32") || target.contains("emscripten") {
+        if !target.contains("wasm") || target.contains("emscripten") {
             builder.ensure(native::TestHelpers { target });
         }
 

From a3b9405ae7bb6ab4e8103b414e75c44598a10fd2 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Mon, 1 Nov 2021 14:32:55 -0700
Subject: [PATCH 08/17] Use more robust checks in rustc for wasm

---
 compiler/rustc_codegen_llvm/src/builder.rs | 4 ++--
 compiler/rustc_codegen_llvm/src/consts.rs  | 2 +-
 compiler/rustc_typeck/src/check/mod.rs     | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 0041a44a4d8..ff88302bf7a 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -769,7 +769,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         // we like. To ensure that LLVM picks the right instruction we choose
         // the raw wasm intrinsic functions which avoid LLVM inserting all the
         // other control flow automatically.
-        if self.sess().target.arch.starts_with("wasm32") {
+        if self.sess().target.is_like_wasm {
             let src_ty = self.cx.val_ty(val);
             if self.cx.type_kind(src_ty) != TypeKind::Vector {
                 let float_width = self.cx.float_width(src_ty);
@@ -791,7 +791,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
     fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         // see `fptoui` above for why wasm is different here
-        if self.sess().target.arch.starts_with("wasm") {
+        if self.sess().target.is_like_wasm {
             let src_ty = self.cx.val_ty(val);
             if self.cx.type_kind(src_ty) != TypeKind::Vector {
                 let float_width = self.cx.float_width(src_ty);
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index cbdc76c55e4..b154ced42f0 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -490,7 +490,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
 
             // Wasm statics with custom link sections get special treatment as they
             // go into custom sections of the wasm executable.
-            if self.tcx.sess.opts.target_triple.triple().starts_with("wasm") {
+            if self.tcx.sess.target.is_like_wasm {
                 if let Some(section) = attrs.link_section {
                     let section = llvm::LLVMMDStringInContext(
                         self.llcx,
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 1404a55bcaa..e7fba3a70ff 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -536,8 +536,8 @@ fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
 }
 
 fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId, span: Span) {
-    // Only restricted on wasm32 target for now
-    if !tcx.sess.opts.target_triple.triple().starts_with("wasm") {
+    // Only restricted on wasm target for now
+    if !tcx.sess.target.is_like_wasm {
         return;
     }
 

From 88f1bf73ee8466d07b1e38755de53a70fc292e20 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Tue, 2 Nov 2021 07:23:41 -0700
Subject: [PATCH 09/17] Update stdarch/compiler_builtins

Brings in some fixes and better support for the wasm64 target.
---
 Cargo.lock             | 4 ++--
 library/std/Cargo.toml | 2 +-
 library/stdarch        | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 7cd07e38472..34a4af96b29 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -678,9 +678,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.49"
+version = "0.1.52"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2"
+checksum = "b6591c2442ee984e2b264638a8b5e7ae44fd47b32d28e3a08e2e9c3cdb0c2fb0"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 752ab185b8e..61c729c5e6c 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -16,7 +16,7 @@ panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
 libc = { version = "0.2.106", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.44" }
+compiler_builtins = { version = "0.1.52" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.11", default-features = false, features = ['rustc-dep-of-std'] }
diff --git a/library/stdarch b/library/stdarch
index 5fdbc476afc..2eb870662be 160000
--- a/library/stdarch
+++ b/library/stdarch
@@ -1 +1 @@
-Subproject commit 5fdbc476afc81a789806697fc4a2d9d19b8c9993
+Subproject commit 2eb870662bed827c808042a27c5e2ac8225cb0f1

From b5c3f4c5d8d7be29e3e45e3961a9764c54744a8d Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Tue, 2 Nov 2021 11:28:54 -0700
Subject: [PATCH 10/17] Update dlmalloc for libstd

This pulls in a fix for wasm64 to work correctly with this dlmalloc
---
 Cargo.lock             | 4 ++--
 library/std/Cargo.toml | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 34a4af96b29..41e5352e817 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1028,9 +1028,9 @@ dependencies = [
 
 [[package]]
 name = "dlmalloc"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "332570860c2edf2d57914987bf9e24835425f75825086b6ba7d1e6a3e4f1f254"
+checksum = "96d075454d918d7358fcd2290dcb4c3ae7bc735388dd1b31ccee1426c1106d8a"
 dependencies = [
  "compiler_builtins",
  "libc",
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 61c729c5e6c..839e9576ce5 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -36,7 +36,7 @@ features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive']
 rand = "0.7"
 
 [target.'cfg(any(all(target_family = "wasm", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
-dlmalloc = { version = "0.2.1", features = ['rustc-dep-of-std'] }
+dlmalloc = { version = "0.2.2", features = ['rustc-dep-of-std'] }
 
 [target.x86_64-fortanix-unknown-sgx.dependencies]
 fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }

From e4b34966184d707ac5e2038e426558211e08ef6d Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Mon, 8 Nov 2021 07:53:35 -0800
Subject: [PATCH 11/17] Update stdarch/dlmalloc

Ensure that they compile with the now-a-feature-is-required logic.
---
 Cargo.lock             | 4 ++--
 library/std/Cargo.toml | 2 +-
 library/stdarch        | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 41e5352e817..28b922cf913 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1028,9 +1028,9 @@ dependencies = [
 
 [[package]]
 name = "dlmalloc"
-version = "0.2.2"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96d075454d918d7358fcd2290dcb4c3ae7bc735388dd1b31ccee1426c1106d8a"
+checksum = "a6fe28e0bf9357092740362502f5cc7955d8dc125ebda71dec72336c2e15c62e"
 dependencies = [
  "compiler_builtins",
  "libc",
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 839e9576ce5..8f43e902a87 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -36,7 +36,7 @@ features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive']
 rand = "0.7"
 
 [target.'cfg(any(all(target_family = "wasm", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
-dlmalloc = { version = "0.2.2", features = ['rustc-dep-of-std'] }
+dlmalloc = { version = "0.2.3", features = ['rustc-dep-of-std'] }
 
 [target.x86_64-fortanix-unknown-sgx.dependencies]
 fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
diff --git a/library/stdarch b/library/stdarch
index 2eb870662be..815d55c610d 160000
--- a/library/stdarch
+++ b/library/stdarch
@@ -1 +1 @@
-Subproject commit 2eb870662bed827c808042a27c5e2ac8225cb0f1
+Subproject commit 815d55c610dab39e92e7c83bf5fd4b7a020b4d46

From 9d6f7f7a57402d5a5cf6725c448b4acf3a24ceab Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Tue, 9 Nov 2021 07:44:42 -0800
Subject: [PATCH 12/17] Add target documentation for wasm64-unknown-unknown

---
 .../wasm64-unknown-unknown.md                 | 101 ++++++++++++++++++
 1 file changed, 101 insertions(+)
 create mode 100644 src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md

diff --git a/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md
new file mode 100644
index 00000000000..021b904debd
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md
@@ -0,0 +1,101 @@
+# `wasm64-unknown-unknown`
+
+**Tier: 3**
+
+WebAssembly target which uses 64-bit memories, relying on the [memory64]
+WebAssembly proposal.
+
+[memory64]: https://github.com/webassembly/memory64
+
+## Target maintainers
+
+- Alex Crichton, https://github.com/alexcrichton
+
+## Requirements
+
+This target is cross-compiled. The target supports `std` in the same manner as
+the `wasm32-unknown-unknown` target which is to say that it comes with the
+standard library but many I/O functions such as `std::fs` and `std::net` will
+simply return error. Additionally I/O operations like `println!` don't actually
+do anything and the prints aren't routed anywhere. This is the same as the
+`wasm32-unknown-unknown` target. This target comes by default with an allocator,
+currently [dlmalloc] which is [ported to rust][dlmalloc-rs].
+
+[dlmalloc]: http://gee.cs.oswego.edu/dl/html/malloc.html
+[dlmalloc-rs]: https://github.com/alexcrichton/dlmalloc-rs
+
+The difference of this target with `wasm32-unknown-unknown` is that it's
+compiled for 64-bit memories instead of 32-bit memories. This means that `usize`
+is 8-bytes large as well as pointers. The tradeoff, though, is that the maximum
+memory size is now the full 64-bit address space instead of the 4GB as limited
+by the 32-bit address space for `wasm32-unknown-unknown`.
+
+This target is not a stable target. The [memory64] WebAssembly proposal is stil
+in-progress and not standardized. This means that there are not many engines
+which implement the `memory64` feature and if they do they're likely behind a
+flag, for example:
+
+* Nodejs - `--experimental-wasm-memory64`
+* Wasmtime - `--wasm-features memory64`
+
+Also note that at this time the `wasm64-unknown-unknown` target assumes the
+presence of other merged wasm proposals such as (with their LLVM feature flags):
+
+* [Bulk memory] - `+bulk-memory`
+* Mutable imported globals - `+mutable-globals`
+* [Sign-extending operations] - `+sign-ext`
+* [Non-trapping fp-to-int operations] - `+nontrapping-fptoint`
+
+[Bulk memory]: https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md
+[Sign-extending operations]: https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md
+[Non-trapping fp-to-int operations]: https://github.com/WebAssembly/spec/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md
+
+The `wasm64-unknown-unknown` target intends to match the default Clang targets
+for its `"C"` ABI, which is likely to be the same as Clang's
+`wasm32-unknown-unknown` largely.
+
+> **Note**: due to the relatively early-days nature of this target when working
+> with this target you may encounter LLVM bugs. If an assertion hit or a bug is
+> found it's recommended to open an issue either with rust-lang/rust or ideally
+> with LLVM itself.
+
+This target does not support `panic=unwind` at this time.
+
+## Building the target
+
+You can build Rust with support for the target by adding it to the `target`
+list in `config.toml`, and the target also requires `lld` to be built to work.
+
+```toml
+[build]
+target = ["wasm64-unknown-unknown"]
+
+[rust]
+lld = true
+```
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target. To compile for
+this target, you will either need to build Rust with the target enabled (see
+"Building the target" above), or build your own copy of `std` by using
+`build-std` or similar.
+
+Note that the following `cfg` directives are set for `wasm64-unknown-unknown`:
+
+* `cfg(target_arch = "wasm64")`
+* `cfg(target_family = "wasm")`
+
+## Testing
+
+Currently testing is not well supported for `wasm64-unknown-unknown` and the
+Rust project doesn't run any tests for this target. Testing support sort of
+works but without `println!` it's not the most exciting tests to run.
+
+## Cross-compilation toolchains and C code
+
+Compiling Rust code with C code for `wasm64-unknown-unknown` is theoretically
+possible, but there are no known toolchains to do this at this time. At the time
+of this writing there is no known "libc" for wasm that works with
+`wasm64-unknown-unknown`, which means that mixing C & Rust with this target
+effectively cannot be done.

From 1d74c77b31a1387512d1fe6cfa24e55548c9ff33 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Tue, 9 Nov 2021 10:51:30 -0600
Subject: [PATCH 13/17] Update src/doc/rustc/src/platform-support.md

Co-authored-by: Josh Triplett <josh@joshtriplett.org>
---
 src/doc/rustc/src/platform-support.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index b749d7f0891..4da3491c586 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -276,7 +276,7 @@ target | std | host | notes
 `thumbv7a-pc-windows-msvc` | ? |  |
 `thumbv7a-uwp-windows-msvc` | ✓ |  |
 `thumbv7neon-unknown-linux-musleabihf` | ? |  | Thumb2-mode ARMv7a Linux with NEON, MUSL
-`wasm64-unknown-unknown` | ? |  | WebAssembly
+[`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? |  | WebAssembly
 `x86_64-apple-ios-macabi` | ✓ |  | Apple Catalyst on x86_64
 `x86_64-apple-tvos` | * | | x86 64-bit tvOS
 `x86_64-pc-windows-msvc` | ✓ |  | 64-bit Windows XP support

From 9a442353f37a9959c2149927382bb8261d980e76 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Tue, 9 Nov 2021 11:17:49 -0800
Subject: [PATCH 14/17] Add a missing doc link

---
 src/doc/rustc/src/SUMMARY.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index c251425d1b7..69a0304d41d 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -16,6 +16,7 @@
     - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md)
     - [\*-kmc-solid_\*](platform-support/kmc-solid.md)
     - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
+    - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
 - [Target Tier Policy](target-tier-policy.md)
 - [Targets](targets/index.md)
     - [Built-in Targets](targets/built-in.md)

From 7dc38369c00380f8ec23f8b3bf4cfc0ea5c94bcf Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Wed, 10 Nov 2021 10:47:00 -0800
Subject: [PATCH 15/17] Disable `.debug_aranges` for all wasm targets

This follows from discussion on
https://bugs.llvm.org/show_bug.cgi?id=52442 where it looks like this
section doesn't make sense for wasm targets.
---
 compiler/rustc_codegen_llvm/src/llvm_util.rs | 10 ++--------
 compiler/rustc_target/src/spec/mod.rs        |  6 ++++++
 compiler/rustc_target/src/spec/wasm_base.rs  |  6 ++++++
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 35a3d21036a..3393c9baa28 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -75,14 +75,8 @@ unsafe fn configure_llvm(sess: &Session) {
         if sess.print_llvm_passes() {
             add("-debug-pass=Structure", false);
         }
-        if !sess.opts.debugging_opts.no_generate_arange_section
-            // FIXME: An LLVM bug [1] means that if this option is enabled for
-            // wasm64 then LLVM will crash when generating debuginfo. Assuming
-            // that this gets fixed in LLVM 14 this condition here is a
-            // workaround to work with versions of LLVM 13 and prior.
-            //
-            // [1]: https://bugs.llvm.org/show_bug.cgi?id=52376
-            && (sess.target.arch != "wasm64" || llvm_util::get_version() >= (14, 0, 0))
+        if sess.target.generate_arange_section
+            && !sess.opts.debugging_opts.no_generate_arange_section
         {
             add("-generate-arange-section", false);
         }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 69b90bf10fe..0771f998535 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1357,6 +1357,9 @@ pub struct TargetOptions {
 
     /// Minimum number of bits in #[repr(C)] enum. Defaults to 32.
     pub c_enum_min_bits: u64,
+
+    /// Whether or not the DWARF `.debug_aranges` section should be generated.
+    pub generate_arange_section: bool,
 }
 
 impl Default for TargetOptions {
@@ -1462,6 +1465,7 @@ impl Default for TargetOptions {
             supported_sanitizers: SanitizerSet::empty(),
             default_adjusted_cabi: None,
             c_enum_min_bits: 32,
+            generate_arange_section: true,
         }
     }
 }
@@ -2047,6 +2051,7 @@ impl Target {
         key!(supported_sanitizers, SanitizerSet)?;
         key!(default_adjusted_cabi, Option<Abi>)?;
         key!(c_enum_min_bits, u64);
+        key!(generate_arange_section, bool);
 
         if base.is_builtin {
             // This can cause unfortunate ICEs later down the line.
@@ -2286,6 +2291,7 @@ impl ToJson for Target {
         target_option_val!(split_debuginfo);
         target_option_val!(supported_sanitizers);
         target_option_val!(c_enum_min_bits);
+        target_option_val!(generate_arange_section);
 
         if let Some(abi) = self.default_adjusted_cabi {
             d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json());
diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs
index 4c954a1e567..24e9c625169 100644
--- a/compiler/rustc_target/src/spec/wasm_base.rs
+++ b/compiler/rustc_target/src/spec/wasm_base.rs
@@ -128,6 +128,12 @@ pub fn options() -> TargetOptions {
         // gdb scripts don't work on wasm blobs
         emit_debug_gdb_scripts: false,
 
+        // There's more discussion of this at
+        // https://bugs.llvm.org/show_bug.cgi?id=52442 but the general result is
+        // that this isn't useful for wasm and has tricky issues with
+        // representation, so this is disabled.
+        generate_arange_section: false,
+
         ..Default::default()
     }
 }

From 97cd27ab1dea10b5f58441f10e9b0771fd827eb8 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Tue, 16 Nov 2021 13:10:35 -0800
Subject: [PATCH 16/17] Add emscripten to the "wasm" family of targets

---
 compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs
index 86b1a755233..69a404ec564 100644
--- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs
+++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs
@@ -37,7 +37,7 @@ pub fn target() -> Target {
         is_like_emscripten: true,
         panic_strategy: PanicStrategy::Unwind,
         post_link_args,
-        families: vec!["unix".to_string()],
+        families: vec!["unix".to_string(), "wasm".to_string()],
         ..options
     };
     Target {

From af217f7f78762184b66957aa87c8d4493d83e86a Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Wed, 17 Nov 2021 10:30:31 -0800
Subject: [PATCH 17/17] Fix emscripten tests

---
 src/test/ui/cfg/cfg-target-family.rs | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/src/test/ui/cfg/cfg-target-family.rs b/src/test/ui/cfg/cfg-target-family.rs
index 90a59fab8e2..5182cdc8940 100644
--- a/src/test/ui/cfg/cfg-target-family.rs
+++ b/src/test/ui/cfg/cfg-target-family.rs
@@ -4,13 +4,10 @@
 // pretty-expanded FIXME #23616
 
 #[cfg(target_family = "windows")]
-pub fn main() {
-}
+pub fn main() {}
 
 #[cfg(target_family = "unix")]
-pub fn main() {
-}
+pub fn main() {}
 
-#[cfg(target_family="wasm")]
-pub fn main() {
-}
+#[cfg(all(target_family = "wasm", not(target_os = "emscripten")))]
+pub fn main() {}