diff --git a/crates/core_arch/src/core_arch_docs.md b/crates/core_arch/src/core_arch_docs.md index 96634f200f..cd981a06be 100644 --- a/crates/core_arch/src/core_arch_docs.md +++ b/crates/core_arch/src/core_arch_docs.md @@ -191,6 +191,7 @@ others at: * [`powerpc64`] * [`nvptx`] * [`wasm32`] +* [`wasm64`] [`x86`]: x86/index.html [`x86_64`]: x86_64/index.html @@ -201,7 +202,8 @@ others at: [`powerpc`]: powerpc/index.html [`powerpc64`]: powerpc64/index.html [`nvptx`]: nvptx/index.html -[`wasm32`]: wasm32/index.html +[`wasm32`]: wasm/index.html +[`wasm64`]: wasm/index.html # Examples diff --git a/crates/core_arch/src/lib.rs b/crates/core_arch/src/lib.rs index b0eea59861..29b52f16aa 100644 --- a/crates/core_arch/src/lib.rs +++ b/crates/core_arch/src/lib.rs @@ -41,7 +41,7 @@ bench_black_box )] #![cfg_attr(test, feature(test, abi_vectorcall))] -#![cfg_attr(all(test, target_arch = "wasm32"), feature(wasm_simd))] +#![cfg_attr(all(test, target_arch = "wasm32", target_arch = "wasm64"), feature(wasm_simd))] #![deny(clippy::missing_inline_in_public_items)] #![allow( clippy::inline_always, diff --git a/crates/core_arch/src/mod.rs b/crates/core_arch/src/mod.rs index 4e6dcb7dc4..d39bd9ead0 100644 --- a/crates/core_arch/src/mod.rs +++ b/crates/core_arch/src/mod.rs @@ -58,117 +58,24 @@ pub mod arch { /// Platform-specific intrinsics for the `wasm32` platform. /// - /// This module provides intrinsics specific to the WebAssembly - /// architecture. Here you'll find intrinsics specific to WebAssembly that - /// aren't otherwise surfaced somewhere in a cross-platform abstraction of - /// `std`, and you'll also find functions for leveraging WebAssembly - /// proposals such as [atomics] and [simd]. - /// - /// Intrinsics in the `wasm32` module are modeled after the WebAssembly - /// instructions that they represent. All functions are named after the - /// instruction they intend to correspond to, and the arguments/results - /// correspond to the type signature of the instruction itself. Stable - /// WebAssembly instructions are [documented online][instrdoc]. - /// - /// [instrdoc]: https://webassembly.github.io/spec/core/valid/instructions.html - /// - /// If a proposal is not yet stable in WebAssembly itself then the functions - /// within this function may be unstable and require the nightly channel of - /// Rust to use. As the proposal itself stabilizes the intrinsics in this - /// module should stabilize as well. - /// - /// [atomics]: https://github.com/webassembly/threads - /// [simd]: https://github.com/webassembly/simd - /// - /// See the [module documentation](../index.html) for general information - /// about the `arch` module and platform intrinsics. - /// - /// ## Atomics - /// - /// The [threads proposal][atomics] for WebAssembly adds a number of - /// instructions for dealing with multithreaded programs. Most instructions - /// added in the [atomics] proposal are exposed in Rust through the - /// `std::sync::atomic` module. Some instructions, however, don't have - /// direct equivalents in Rust so they're exposed here instead. - /// - /// Note that the instructions added in the [atomics] proposal can work in - /// either a context with a shared wasm memory and without. These intrinsics - /// are always available in the standard library, but you likely won't be - /// able to use them too productively unless you recompile the standard - /// library (and all your code) with `-Ctarget-feature=+atomics`. - /// - /// It's also worth pointing out that multi-threaded WebAssembly and its - /// story in Rust is still in a somewhat "early days" phase as of the time - /// of this writing. Pieces should mostly work but it generally requires a - /// good deal of manual setup. At this time it's not as simple as "just call - /// `std::thread::spawn`", but it will hopefully get there one day! - /// - /// ## SIMD - /// - /// The [simd proposal][simd] for WebAssembly adds a new `v128` type for a - /// 128-bit SIMD register. It also adds a large array of instructions to - /// operate on the `v128` type to perform data processing. The SIMD proposal - /// at the time of this writing is in [phase 4] which means that it's in the - /// standardization phase. It's expected that once some testing on nightly - /// has happened a stabilization proposal will be made for the Rust - /// intrinsics. If you notice anything awry please feel free to [open an - /// issue](https://github.com/rust-lang/stdarch/issues/new). - /// - /// [phase 4]: https://github.com/webassembly/proposals - /// - /// Using SIMD is intended to be similar to as you would on `x86_64`, for - /// example. You'd write a function such as: - /// - /// ```rust,ignore - /// #[cfg(target_arch = "wasm32")] - /// #[target_feature(enable = "simd128")] - /// unsafe fn uses_simd() { - /// use std::arch::wasm32::*; - /// // ... - /// } - /// ``` - /// - /// Unlike `x86_64`, however, WebAssembly does not currently have dynamic - /// detection at runtime as to whether SIMD is supported (this is one of the - /// motivators for the [conditional sections][condsections] and [feature - /// detection] proposals, but that is still pretty early days). This means - /// that your binary will either have SIMD and can only run on engines - /// which support SIMD, or it will not have SIMD at all. For compatibility - /// the standard library itself does not use any SIMD internally. - /// Determining how best to ship your WebAssembly binary with SIMD is - /// largely left up to you as it can can be pretty nuanced depending on - /// your situation. - /// - /// [condsections]: https://github.com/webassembly/conditional-sections - /// [feature detection]: https://github.com/WebAssembly/feature-detection - /// - /// To enable SIMD support at compile time you need to do one of two things: - /// - /// * First you can annotate functions with `#[target_feature(enable = - /// "simd128")]`. This causes just that one function to have SIMD support - /// available to it, and intrinsics will get inlined as usual in this - /// situation. - /// - /// * Second you can compile your program with `-Ctarget-feature=+simd128`. - /// This compilation flag blanket enables SIMD support for your entire - /// compilation. Note that this does not include the standard library - /// unless you [recompile the standard library][buildstd]. - /// - /// [buildstd]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std - /// - /// If you enable SIMD via either of these routes then you'll have a - /// WebAssembly binary that uses SIMD instructions, and you'll need to ship - /// that accordingly. Also note that if you call SIMD intrinsics but don't - /// enable SIMD via either of these mechanisms, you'll still have SIMD - /// generated in your program. This means to generate a binary without SIMD - /// you'll need to avoid both options above plus calling into any intrinsics - /// in this module. + /// See the [module documentation](../index.html) for more details. #[cfg(any(target_arch = "wasm32", doc))] #[doc(cfg(target_arch = "wasm32"))] #[stable(feature = "simd_wasm32", since = "1.33.0")] pub mod wasm32 { #[stable(feature = "simd_wasm32", since = "1.33.0")] - pub use crate::core_arch::wasm32::*; + pub use crate::core_arch::wasm::*; + } + + /// Platform-specific intrinsics for the `wasm64` platform. + /// + /// See the [module documentation](../index.html) for more details. + #[cfg(any(target_arch = "wasm64", doc))] + #[doc(cfg(target_arch = "wasm64"))] + #[stable(feature = "", since = "0.0.0")] + pub mod wasm64 { + #[stable(feature = "", since = "0.0.0")] + pub use crate::core_arch::wasm::*; } /// Platform-specific intrinsics for the `mips` platform. @@ -238,9 +145,9 @@ mod aarch64; #[doc(cfg(any(target_arch = "arm")))] mod arm; -#[cfg(any(target_arch = "wasm32", doc))] -#[doc(cfg(target_arch = "wasm32"))] -mod wasm32; +#[cfg(any(target_arch = "wasm32", target_arch = "wasm64", doc))] +#[doc(cfg(any(target_arch = "wasm32", target_arch = "wasm64")))] +mod wasm; #[cfg(any(target_arch = "mips", target_arch = "mips64", doc))] #[doc(cfg(any(target_arch = "mips", target_arch = "mips64")))] diff --git a/crates/core_arch/src/wasm32/atomic.rs b/crates/core_arch/src/wasm/atomic.rs similarity index 100% rename from crates/core_arch/src/wasm32/atomic.rs rename to crates/core_arch/src/wasm/atomic.rs diff --git a/crates/core_arch/src/wasm32/memory.rs b/crates/core_arch/src/wasm/memory.rs similarity index 89% rename from crates/core_arch/src/wasm32/memory.rs rename to crates/core_arch/src/wasm/memory.rs index 19fbd48d0c..cebcc04a38 100644 --- a/crates/core_arch/src/wasm32/memory.rs +++ b/crates/core_arch/src/wasm/memory.rs @@ -2,10 +2,10 @@ use stdarch_test::assert_instr; extern "C" { - #[link_name = "llvm.wasm.memory.grow.i32"] - fn llvm_memory_grow(mem: u32, pages: i32) -> i32; - #[link_name = "llvm.wasm.memory.size.i32"] - fn llvm_memory_size(mem: u32) -> i32; + #[link_name = "llvm.wasm.memory.grow"] + fn llvm_memory_grow(mem: u32, pages: isize) -> isize; + #[link_name = "llvm.wasm.memory.size"] + fn llvm_memory_size(mem: u32) -> isize; } /// Corresponding intrinsic to wasm's [`memory.size` instruction][instr] @@ -51,6 +51,6 @@ pub fn memory_size() -> usize { pub fn memory_grow(delta: usize) -> usize { unsafe { static_assert!(MEM: u32 where MEM == 0); - llvm_memory_grow(MEM, delta as i32) as isize as usize + llvm_memory_grow(MEM, delta as isize) as usize } } diff --git a/crates/core_arch/src/wasm/mod.rs b/crates/core_arch/src/wasm/mod.rs new file mode 100644 index 0000000000..9e95f03d4b --- /dev/null +++ b/crates/core_arch/src/wasm/mod.rs @@ -0,0 +1,127 @@ +//! This module provides intrinsics specific to the WebAssembly +//! architecture. Here you'll find intrinsics specific to WebAssembly that +//! aren't otherwise surfaced somewhere in a cross-platform abstraction of +//! `std`, and you'll also find functions for leveraging WebAssembly +//! proposals such as [atomics] and [simd]. +//! +//! Intrinsics in this module are modeled after the WebAssembly instructions +//! that they represent. All functions are named after the instruction they +//! intend to correspond to, and the arguments/results correspond to the type +//! signature of the instruction itself. Stable WebAssembly instructions are +//! [documented online][instrdoc]. +//! +//! [instrdoc]: https://webassembly.github.io/spec/core/valid/instructions.html +//! +//! If a proposal is not yet stable in WebAssembly itself then the functions +//! within this function may be unstable and require the nightly channel of +//! Rust to use. As the proposal itself stabilizes the intrinsics in this +//! module should stabilize as well. +//! +//! [atomics]: https://github.com/webassembly/threads +//! [simd]: https://github.com/webassembly/simd +//! +//! See the [module documentation](../index.html) for general information +//! about the `arch` module and platform intrinsics. +//! +//! ## Atomics +//! +//! The [threads proposal][atomics] for WebAssembly adds a number of +//! instructions for dealing with multithreaded programs. Most instructions +//! added in the [atomics] proposal are exposed in Rust through the +//! `std::sync::atomic` module. Some instructions, however, don't have +//! direct equivalents in Rust so they're exposed here instead. +//! +//! Note that the instructions added in the [atomics] proposal can work in +//! either a context with a shared wasm memory and without. These intrinsics +//! are always available in the standard library, but you likely won't be +//! able to use them too productively unless you recompile the standard +//! library (and all your code) with `-Ctarget-feature=+atomics`. +//! +//! It's also worth pointing out that multi-threaded WebAssembly and its +//! story in Rust is still in a somewhat "early days" phase as of the time +//! of this writing. Pieces should mostly work but it generally requires a +//! good deal of manual setup. At this time it's not as simple as "just call +//! `std::thread::spawn`", but it will hopefully get there one day! +//! +//! ## SIMD +//! +//! The [simd proposal][simd] for WebAssembly adds a new `v128` type for a +//! 128-bit SIMD register. It also adds a large array of instructions to +//! operate on the `v128` type to perform data processing. The SIMD proposal +//! at the time of this writing is in [phase 4] which means that it's in the +//! standardization phase. It's expected that once some testing on nightly +//! has happened a stabilization proposal will be made for the Rust +//! intrinsics. If you notice anything awry please feel free to [open an +//! issue](https://github.com/rust-lang/stdarch/issues/new). +//! +//! [phase 4]: https://github.com/webassembly/proposals +//! +//! Using SIMD is intended to be similar to as you would on `x86_64`, for +//! example. You'd write a function such as: +//! +//! ```rust,ignore +//! #[target_feature(enable = "simd128")] +//! unsafe fn uses_simd() { +//! #[cfg(target_arch = "wasm32")] +//! use std::arch::wasm32::*; +//! #[cfg(target_arch = "wasm64")] +//! use std::arch::wasm64::*; +//! // ... +//! } +//! ``` +//! +//! Unlike `x86_64`, however, WebAssembly does not currently have dynamic +//! detection at runtime as to whether SIMD is supported (this is one of the +//! motivators for the [conditional sections][condsections] and [feature +//! detection] proposals, but that is still pretty early days). This means +//! that your binary will either have SIMD and can only run on engines +//! which support SIMD, or it will not have SIMD at all. For compatibility +//! the standard library itself does not use any SIMD internally. +//! Determining how best to ship your WebAssembly binary with SIMD is +//! largely left up to you as it can can be pretty nuanced depending on +//! your situation. +//! +//! [condsections]: https://github.com/webassembly/conditional-sections +//! [feature detection]: https://github.com/WebAssembly/feature-detection +//! +//! To enable SIMD support at compile time you need to do one of two things: +//! +//! * First you can annotate functions with `#[target_feature(enable = +//! "simd128")]`. This causes just that one function to have SIMD support +//! available to it, and intrinsics will get inlined as usual in this +//! situation. +//! +//! * Second you can compile your program with `-Ctarget-feature=+simd128`. +//! This compilation flag blanket enables SIMD support for your entire +//! compilation. Note that this does not include the standard library +//! unless you [recompile the standard library][buildstd]. +//! +//! [buildstd]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std +//! +//! If you enable SIMD via either of these routes then you'll have a +//! WebAssembly binary that uses SIMD instructions, and you'll need to ship +//! that accordingly. Also note that if you call SIMD intrinsics but don't +//! enable SIMD via either of these mechanisms, you'll still have SIMD +//! generated in your program. This means to generate a binary without SIMD +//! you'll need to avoid both options above plus calling into any intrinsics +//! in this module. + +#[cfg(test)] +use stdarch_test::assert_instr; + +mod atomic; +pub use self::atomic::*; + +mod simd128; +pub use self::simd128::*; + +mod memory; +pub use self::memory::*; + +/// Generates the trap instruction `UNREACHABLE` +#[cfg_attr(test, assert_instr(unreachable))] +#[inline] +#[stable(feature = "unreachable_wasm32", since = "1.37.0")] +pub unsafe fn unreachable() -> ! { + crate::intrinsics::abort() +} diff --git a/crates/core_arch/src/wasm32/simd128.rs b/crates/core_arch/src/wasm/simd128.rs similarity index 100% rename from crates/core_arch/src/wasm32/simd128.rs rename to crates/core_arch/src/wasm/simd128.rs diff --git a/crates/core_arch/src/wasm32/mod.rs b/crates/core_arch/src/wasm32/mod.rs deleted file mode 100644 index 9052772894..0000000000 --- a/crates/core_arch/src/wasm32/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -//! WASM32 intrinsics - -#[cfg(test)] -use stdarch_test::assert_instr; - -mod atomic; -pub use self::atomic::*; - -mod simd128; -pub use self::simd128::*; - -mod memory; -pub use self::memory::*; - -/// Generates the trap instruction `UNREACHABLE` -#[cfg_attr(test, assert_instr(unreachable))] -#[inline] -#[stable(feature = "unreachable_wasm32", since = "1.37.0")] -pub unsafe fn unreachable() -> ! { - crate::intrinsics::abort() -}