Auto merge of #90382 - alexcrichton:wasm64-libstd, r=joshtriplett

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.
This commit is contained in:
bors 2021-11-18 17:19:27 +00:00
commit b6f580acc0
31 changed files with 183 additions and 60 deletions

View File

@ -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",
@ -1028,9 +1028,9 @@ dependencies = [
[[package]]
name = "dlmalloc"
version = "0.2.1"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "332570860c2edf2d57914987bf9e24835425f75825086b6ba7d1e6a3e4f1f254"
checksum = "a6fe28e0bf9357092740362502f5cc7955d8dc125ebda71dec72336c2e15c62e"
dependencies = [
"compiler_builtins",
"libc",

View File

@ -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 => {}
}
}

View File

@ -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.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 == "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);

View File

@ -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.target.is_like_wasm {
if let Some(section) = attrs.link_section {
let section = llvm::LLVMMDStringInContext(
self.llcx,

View File

@ -75,7 +75,9 @@ 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.target.generate_arange_section
&& !sess.opts.debugging_opts.no_generate_arange_section
{
add("-generate-arange-section", false);
}

View File

@ -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

View File

@ -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());

View File

@ -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 {

View File

@ -23,11 +23,15 @@ 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());
// 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(),

View File

@ -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()
}
}

View File

@ -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("wasm32") {
// Only restricted on wasm target for now
if !tcx.sess.target.is_like_wasm {
return;
}

View File

@ -62,7 +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_family = "wasm",
target_arch = "asmjs",
windows
))]
@ -85,7 +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_family = "wasm",
target_arch = "asmjs",
windows
))]
@ -185,7 +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_family = "wasm",
target_arch = "asmjs",
windows
))]
@ -194,7 +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_family = "wasm"),
not(target_arch = "asmjs"),
not(windows)
))]
@ -206,7 +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_family = "wasm",
target_arch = "asmjs",
windows
))]
@ -227,7 +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_family = "wasm"),
not(target_arch = "asmjs"),
not(windows)
))]

View File

@ -117,7 +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_family = "wasm", not(target_os = "emscripten")),
all(target_os = "windows", target_env = "gnu", target_arch = "x86_64",),
)))]
pub extern "C" fn rust_eh_personality() {}

View File

@ -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;

View File

@ -56,7 +56,7 @@ cfg_if::cfg_if! {
mod real_imp;
} else {
// Targets that don't support unwinding.
// - arch=wasm32
// - family=wasm
// - os=none ("bare metal" targets)
// - os=uefi
// - os=espidf

View File

@ -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'] }
@ -35,8 +35,8 @@ 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]
dlmalloc = { version = "0.2.1", features = ['rustc-dep-of-std'] }
[target.'cfg(any(all(target_family = "wasm", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
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'] }

View File

@ -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")

View File

@ -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;

View File

@ -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(target_family = "wasm")] {
mod wasm;
pub use self::wasm::*;
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {

View File

@ -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 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!
//!
//! 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

View File

@ -40,7 +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_family = "wasm", not(target_os = "emscripten")),
all(target_vendor = "fortanix", target_env = "sgx")))] {
pub use crate::sys::net;
} else {

View File

@ -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(target_family = "wasm", not(target_feature = "atomics")))]
{
static mut VAL: $t = $init;
Some(&VAL)
@ -181,7 +181,7 @@ 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(target_family = "wasm", not(target_feature = "atomics"))),
))]
{
// If a dtor isn't needed we can do something "very raw" and
@ -238,7 +238,7 @@ 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(target_family = "wasm", not(target_feature = "atomics"))),
))]
{
#[inline]
@ -285,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(target_arch = "wasm32", 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(target_arch = "wasm32", 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(target_arch = "wasm32", not(target_feature = "atomics"))),
not(all(target_family = "wasm", not(target_feature = "atomics"))),
))]
static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
$crate::thread::__OsLocalKeyInner::new();
@ -479,10 +479,10 @@ mod lazy {
}
}
/// On some platforms like wasm32 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_arch = "wasm32", not(target_feature = "atomics")))]
#[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
pub mod statik {
use super::lazy::LazyKeyInner;
use crate::fmt;

View File

@ -200,7 +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(target_arch = "wasm32", not(target_feature = "atomics")))]
#[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
#[doc(hidden)]
pub use self::local::statik::Key as __StaticLocalKeyInner;

@ -1 +1 @@
Subproject commit 5fdbc476afc81a789806697fc4a2d9d19b8c9993
Subproject commit 815d55c610dab39e92e7c83bf5fd4b7a020b4d46

View File

@ -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))?;

View File

@ -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)));

View File

@ -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 });
}

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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() {}