Skip to content

Commit

Permalink
Update to stabilized s390x asm
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Nov 11, 2024
1 parent 16816f4 commit 97645c1
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 17 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ jobs:
- rust: nightly
target: riscv64gc-unknown-linux-gnu
flags: -Z codegen-backend=cranelift
# - rust: '1.84' # LLVM 19 (oldest stable version we can use asm on this target)
# target: s390x-unknown-linux-gnu
- rust: nightly-2023-05-09 # Rust 1.71, LLVM 16 (oldest version we can use asm_experimental_arch on this target)
target: s390x-unknown-linux-gnu
# - rust: nightly-2024-02-13 # Rust 1.78, LLVM 17
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ portable-atomic = { version = "1.3", default-features = false, features = ["requ

## 128-bit atomics support

Native 128-bit atomic operations are available on x86_64 (Rust 1.59+), AArch64 (Rust 1.59+), riscv64 (Rust 1.59+), powerpc64 (nightly only), s390x (nightly only), and Arm64EC (nightly only), otherwise the fallback implementation is used.
Native 128-bit atomic operations are available on x86_64 (Rust 1.59+), AArch64 (Rust 1.59+), riscv64 (Rust 1.59+), s390x (Rust 1.84+), Arm64EC (nightly only), and powerpc64 (nightly only), otherwise the fallback implementation is used.

On x86_64, even if `cmpxchg16b` is not available at compile-time (note: `cmpxchg16b` target feature is enabled by default only on Apple and Windows (except Windows 7) targets), run-time detection checks whether `cmpxchg16b` is available. If `cmpxchg16b` is not available at either compile-time or run-time detection, the fallback implementation is used. See also [`portable_atomic_no_outline_atomics`](#optional-cfg-no-outline-atomics) cfg.

Expand Down
27 changes: 23 additions & 4 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fn main() {
// Custom cfgs set by build script. Not public API.
// grep -F 'cargo:rustc-cfg=' build.rs | grep -Ev '^ *//' | sed -E 's/^.*cargo:rustc-cfg=//; s/(=\\)?".*$//' | LC_ALL=C sort -u | tr '\n' ',' | sed -E 's/,$/\n/'
println!(
"cargo:rustc-check-cfg=cfg(portable_atomic_disable_fiq,portable_atomic_force_amo,portable_atomic_ll_sc_rmw,portable_atomic_new_atomic_intrinsics,portable_atomic_no_asm,portable_atomic_no_asm_maybe_uninit,portable_atomic_no_atomic_64,portable_atomic_no_atomic_cas,portable_atomic_no_atomic_load_store,portable_atomic_no_atomic_min_max,portable_atomic_no_cfg_target_has_atomic,portable_atomic_no_cmpxchg16b_intrinsic,portable_atomic_no_cmpxchg16b_target_feature,portable_atomic_no_const_mut_refs,portable_atomic_no_offset_of,portable_atomic_no_const_raw_ptr_deref,portable_atomic_no_const_transmute,portable_atomic_no_core_unwind_safe,portable_atomic_no_diagnostic_namespace,portable_atomic_no_stronger_failure_ordering,portable_atomic_no_track_caller,portable_atomic_no_unsafe_op_in_unsafe_fn,portable_atomic_pre_llvm_15,portable_atomic_pre_llvm_16,portable_atomic_pre_llvm_18,portable_atomic_s_mode,portable_atomic_sanitize_thread,portable_atomic_target_feature,portable_atomic_unsafe_assume_single_core,portable_atomic_unstable_asm,portable_atomic_unstable_asm_experimental_arch,portable_atomic_unstable_cfg_target_has_atomic,portable_atomic_unstable_isa_attribute)"
"cargo:rustc-check-cfg=cfg(portable_atomic_disable_fiq,portable_atomic_force_amo,portable_atomic_ll_sc_rmw,portable_atomic_new_atomic_intrinsics,portable_atomic_no_asm,portable_atomic_no_asm_maybe_uninit,portable_atomic_no_atomic_64,portable_atomic_no_atomic_cas,portable_atomic_no_atomic_load_store,portable_atomic_no_atomic_min_max,portable_atomic_no_cfg_target_has_atomic,portable_atomic_no_cmpxchg16b_intrinsic,portable_atomic_no_cmpxchg16b_target_feature,portable_atomic_no_const_mut_refs,portable_atomic_no_const_raw_ptr_deref,portable_atomic_no_const_transmute,portable_atomic_no_core_unwind_safe,portable_atomic_no_diagnostic_namespace,portable_atomic_no_offset_of,portable_atomic_no_stronger_failure_ordering,portable_atomic_no_track_caller,portable_atomic_no_unsafe_op_in_unsafe_fn,portable_atomic_pre_llvm_15,portable_atomic_pre_llvm_16,portable_atomic_pre_llvm_18,portable_atomic_s_mode,portable_atomic_sanitize_thread,portable_atomic_target_feature,portable_atomic_unsafe_assume_single_core,portable_atomic_unstable_asm,portable_atomic_unstable_asm_experimental_arch,portable_atomic_unstable_cfg_target_has_atomic,portable_atomic_unstable_isa_attribute)"
);
// TODO: handle multi-line target_feature_fallback
// grep -F 'target_feature_fallback("' build.rs | grep -Ev '^ *//' | sed -E 's/^.*target_feature_fallback\(//; s/",.*$/"/' | LC_ALL=C sort -u | tr '\n' ',' | sed -E 's/,$/\n/'
Expand Down Expand Up @@ -127,7 +127,7 @@ fn main() {
println!("cargo:rustc-cfg=portable_atomic_no_const_mut_refs");
}

// asm stabilized in Rust 1.59 (nightly-2021-12-16): https://github.com/rust-lang/rust/pull/91728
// asm! on AArch64, Arm, RISC-V, x86, and x86_64 stabilized in Rust 1.59 (nightly-2021-12-16): https://github.com/rust-lang/rust/pull/91728
let no_asm = !version.probe(59, 2021, 12, 15);
if no_asm {
if version.nightly
Expand All @@ -145,6 +145,27 @@ fn main() {
println!("cargo:rustc-cfg=portable_atomic_unstable_asm");
}
println!("cargo:rustc-cfg=portable_atomic_no_asm");
} else {
match target_arch {
"s390x" => {
// asm! on s390x stabilized in Rust 1.84 (nightly-2024-11-11): https://github.com/rust-lang/rust/pull/131258
if !version.probe(84, 2024, 11, 10) {
if version.nightly
&& version.probe(71, 2023, 5, 8)
&& is_allowed_feature("asm_experimental_arch")
{
// https://github.com/rust-lang/rust/pull/111331 merged in Rust 1.71 (nightly-2023-05-09).
// The part of this feature we use has not been changed since nightly-2023-05-09
// until it was stabilized in nightly-2024-11-11, so it can be safely enabled in
// nightly, which is older than nightly-2024-11-11.
println!("cargo:rustc-cfg=portable_atomic_unstable_asm_experimental_arch");
} else {
println!("cargo:rustc-cfg=portable_atomic_no_asm");
}
}
}
_ => {}
}
}

// feature(cfg_target_has_atomic) stabilized in Rust 1.60 (nightly-2022-02-11): https://github.com/rust-lang/rust/pull/93824
Expand Down Expand Up @@ -197,10 +218,8 @@ fn main() {
}

// https://github.com/rust-lang/rust/pull/93868 merged in Rust 1.60 (nightly-2022-02-13).
// https://github.com/rust-lang/rust/pull/111331 merged in Rust 1.71 (nightly-2023-05-09).
if !no_asm
&& (target_arch == "powerpc64" && version.probe(60, 2022, 2, 12)
|| target_arch == "s390x" && version.probe(71, 2023, 5, 8)
|| target_arch == "arm64ec")
&& is_allowed_feature("asm_experimental_arch")
{
Expand Down
4 changes: 2 additions & 2 deletions src/cfgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ mod atomic_64_macros {
),
),
),
all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch),
all(target_arch = "s390x", not(portable_atomic_no_asm)),
))
)]
#[cfg_attr(
Expand Down Expand Up @@ -427,7 +427,7 @@ mod atomic_128_macros {
),
),
),
all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch),
all(target_arch = "s390x", not(portable_atomic_no_asm)),
)))
)]
#[cfg_attr(
Expand Down
2 changes: 1 addition & 1 deletion src/imp/atomic128/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Here is the table of targets that support 128-bit atomics and the instructions u
| aarch64/arm64ec | ldxp/stxp or casp or ldp/ldiapp | ldxp/stxp or casp or stp/stilp/swpp | ldxp/stxp or casp | ldxp/stxp or casp/swpp/ldclrp/ldsetp | casp requires lse target feature, ldp/stp requires lse2 target feature, ldiapp/stilp requires lse2 and rcpc3 target features, swpp/ldclrp/ldsetp requires lse128 target feature. <br> Both compile-time and run-time detection are supported. <br> Requires rustc 1.59+ (aarch64) / nightly (arm64ec) |
| riscv64 | amocas.q | amocas.q | amocas.q | amocas.q | Experimental because LLVM marking the corresponding target feature as experimental. Requires experimental-zacas target feature. Both compile-time and run-time detection are supported (run-time detection is currently disabled by default). <br> Requires rustc 1.59+ |
| powerpc64 | lq | stq | lqarx/stqcx. | lqarx/stqcx. | Requires target-cpu pwr8+ (powerpc64le is pwr8 by default). Both compile-time and run-time detection are supported. <br> Requires nightly |
| s390x | lpq | stpq | cdsg | cdsg | Requires nightly |
| s390x | lpq | stpq | cdsg | cdsg | Requires rustc 1.84+ |

On compiler versions or platforms where these are not supported, the fallback implementation is used.

Expand Down
2 changes: 1 addition & 1 deletion src/imp/atomic128/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub(super) mod powerpc64;
pub(super) mod riscv64;

// s390x
#[cfg(all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch))]
#[cfg(all(target_arch = "s390x", not(portable_atomic_no_asm)))]
// Use intrinsics.rs on Miri and Sanitizer that do not support inline assembly.
#[cfg_attr(any(miri, portable_atomic_sanitize_thread), path = "intrinsics.rs")]
pub(super) mod s390x;
Expand Down
6 changes: 3 additions & 3 deletions src/imp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ mod atomic128;
portable_atomic_target_feature = "quadword-atomics",
),
),
all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch),
all(target_arch = "s390x", not(portable_atomic_no_asm)),
))
))]
mod fallback;
Expand Down Expand Up @@ -363,7 +363,7 @@ items! {
),
),
),
all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch),
all(target_arch = "s390x", not(portable_atomic_no_asm)),
)))]
pub(crate) use self::fallback::{AtomicI128, AtomicU128};
}
Expand Down Expand Up @@ -475,5 +475,5 @@ pub(crate) use self::atomic128::riscv64::{AtomicI128, AtomicU128};
))]
pub(crate) use self::atomic128::powerpc64::{AtomicI128, AtomicU128};
// s390x
#[cfg(all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch))]
#[cfg(all(target_arch = "s390x", not(portable_atomic_no_asm)))]
pub(crate) use self::atomic128::s390x::{AtomicI128, AtomicU128};
11 changes: 7 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ portable-atomic = { version = "1.3", default-features = false, features = ["requ
## 128-bit atomics support
Native 128-bit atomic operations are available on x86_64 (Rust 1.59+), AArch64 (Rust 1.59+), riscv64 (Rust 1.59+), powerpc64 (nightly only), s390x (nightly only), and Arm64EC (nightly only), otherwise the fallback implementation is used.
Native 128-bit atomic operations are available on x86_64 (Rust 1.59+), AArch64 (Rust 1.59+), riscv64 (Rust 1.59+), s390x (Rust 1.84+), Arm64EC (nightly only), and powerpc64 (nightly only), otherwise the fallback implementation is used.
On x86_64, even if `cmpxchg16b` is not available at compile-time (note: `cmpxchg16b` target feature is enabled by default only on Apple and Windows (except Windows 7) targets), run-time detection checks whether `cmpxchg16b` is available. If `cmpxchg16b` is not available at either compile-time or run-time detection, the fallback implementation is used. See also [`portable_atomic_no_outline_atomics`](#optional-cfg-no-outline-atomics) cfg.
Expand Down Expand Up @@ -215,7 +215,7 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ...
#![allow(clippy::inline_always, clippy::used_underscore_items)]
// asm_experimental_arch
// AVR, MSP430, and Xtensa are tier 3 platforms and require nightly anyway.
// On tier 2 platforms (arm64ec, powerpc64, and s390x), we use cfg set by build script to
// On tier 2 platforms (arm64ec and powerpc64), we use cfg set by build script to
// determine whether this feature is available or not.
#![cfg_attr(
all(
Expand All @@ -226,7 +226,6 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ...
all(target_arch = "xtensa", portable_atomic_unsafe_assume_single_core),
all(target_arch = "arm64ec", portable_atomic_unstable_asm_experimental_arch),
all(target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch),
all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch),
),
),
feature(asm_experimental_arch)
Expand All @@ -235,7 +234,7 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ...
// These features are already stabilized or have already been removed from compilers,
// and can safely be enabled for old nightly as long as version detection works.
// - cfg(target_has_atomic)
// - asm! on Arm, AArch64, RISC-V, x86, x86_64
// - asm! on AArch64, Arm, RISC-V, x86, x86_64, s390x
// - llvm_asm! on AVR (tier 3) and MSP430 (tier 3)
// - #[instruction_set] on non-Linux/Android pre-v6 Arm (tier 3)
// This also helps us test that our assembly code works with the minimum external
Expand All @@ -255,6 +254,10 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ...
),
feature(asm)
)]
#![cfg_attr(
all(portable_atomic_unstable_asm_experimental_arch, target_arch = "s390x"),
feature(asm_experimental_arch)
)]
#![cfg_attr(
all(any(target_arch = "avr", target_arch = "msp430"), portable_atomic_no_asm),
feature(llvm_asm)
Expand Down
2 changes: 1 addition & 1 deletion src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ fn test_is_lock_free() {
portable_atomic_target_feature = "quadword-atomics",
),
),
all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch),
all(target_arch = "s390x", not(portable_atomic_no_asm)),
)) {
assert!(AtomicI128::is_always_lock_free());
assert!(AtomicI128::is_lock_free());
Expand Down

0 comments on commit 97645c1

Please sign in to comment.