Skip to content

Commit 10c7f4d

Browse files
committed
detect: Support run-time detection on powerpc64 AIX
1 parent ac6ae91 commit 10c7f4d

13 files changed

Lines changed: 139 additions & 84 deletions

File tree

‎.github/.cspell/project-dictionary.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ fistp
5050
getauxval
5151
getisax
5252
getpid
53+
getsystemcfg
5354
gimli
5455
Halfword
5556
HWCAP

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ...
179179
- Dynamic detection is currently only supported in x86_64, AArch64, Arm, RISC-V (disabled by default), Arm64EC, and powerpc64, otherwise it works the same as when this cfg is set.
180180
- If the required target features are enabled at compile-time, the atomic operations are inlined.
181181
- This is compatible with no-std (as with all features except `std`).
182-
- On some targets, run-time detection is disabled by default mainly for incomplete build environments, and can be enabled by `--cfg portable_atomic_outline_atomics`. (When both cfg are enabled, `*_no_*` cfg is preferred.)
182+
- On some targets, run-time detection is disabled by default mainly for compatibility with incomplete build environments or support for it is experimental, and can be enabled by `--cfg portable_atomic_outline_atomics`. (When both cfg are enabled, `*_no_*` cfg is preferred.)
183183
- Some AArch64 targets enable LLVM's `outline-atomics` target feature by default, so if you set this cfg, you may want to disable that as well. (portable-atomic's outline-atomics does not depend on the compiler-rt symbols, so even if you need to disable LLVM's outline-atomics, you may not need to disable portable-atomic's outline-atomics.)
184184

185185
See also the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md).

‎build.rs‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ fn main() {
5454
// Custom cfgs set by build script. Not public API.
5555
// 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/'
5656
println!(
57-
"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_strict_provenance,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)"
57+
"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_strict_provenance,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_pre_llvm_20,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)"
5858
);
5959
// TODO: handle multi-line target_feature_fallback
6060
// 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/'
@@ -207,12 +207,15 @@ fn main() {
207207
println!("cargo:rustc-cfg=portable_atomic_no_atomic_load_store");
208208
}
209209

210-
if version.llvm < 18 {
211-
println!("cargo:rustc-cfg=portable_atomic_pre_llvm_18");
212-
if version.llvm < 16 {
213-
println!("cargo:rustc-cfg=portable_atomic_pre_llvm_16");
214-
if version.llvm < 15 {
215-
println!("cargo:rustc-cfg=portable_atomic_pre_llvm_15");
210+
if version.llvm < 20 {
211+
println!("cargo:rustc-cfg=portable_atomic_pre_llvm_20");
212+
if version.llvm < 18 {
213+
println!("cargo:rustc-cfg=portable_atomic_pre_llvm_18");
214+
if version.llvm < 16 {
215+
println!("cargo:rustc-cfg=portable_atomic_pre_llvm_16");
216+
if version.llvm < 15 {
217+
println!("cargo:rustc-cfg=portable_atomic_pre_llvm_15");
218+
}
216219
}
217220
}
218221
}

‎src/cfgs.rs‎

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -265,11 +265,6 @@ mod atomic_64_macros {
265265
any(
266266
target_feature = "cmpxchg16b",
267267
portable_atomic_target_feature = "cmpxchg16b",
268-
all(
269-
feature = "fallback",
270-
not(portable_atomic_no_outline_atomics),
271-
not(any(target_env = "sgx", miri)),
272-
),
273268
),
274269
),
275270
all(
@@ -278,13 +273,6 @@ mod atomic_64_macros {
278273
any(
279274
target_feature = "experimental-zacas",
280275
portable_atomic_target_feature = "experimental-zacas",
281-
all(
282-
feature = "fallback",
283-
not(portable_atomic_no_outline_atomics),
284-
any(test, portable_atomic_outline_atomics), // TODO(riscv): currently disabled by default
285-
any(target_os = "linux", target_os = "android"),
286-
not(any(miri, portable_atomic_sanitize_thread)),
287-
),
288276
),
289277
),
290278
all(
@@ -293,30 +281,6 @@ mod atomic_64_macros {
293281
any(
294282
target_feature = "quadword-atomics",
295283
portable_atomic_target_feature = "quadword-atomics",
296-
all(
297-
feature = "fallback",
298-
not(portable_atomic_no_outline_atomics),
299-
any(
300-
all(
301-
target_os = "linux",
302-
any(
303-
all(
304-
target_env = "gnu",
305-
any(target_endian = "little", not(target_feature = "crt-static")),
306-
),
307-
all(
308-
any(target_env = "musl", target_env = "ohos", target_env = "uclibc"),
309-
not(target_feature = "crt-static"),
310-
),
311-
portable_atomic_outline_atomics,
312-
),
313-
),
314-
target_os = "android",
315-
target_os = "freebsd",
316-
target_os = "openbsd",
317-
),
318-
not(any(miri, portable_atomic_sanitize_thread)),
319-
),
320284
),
321285
),
322286
all(target_arch = "s390x", not(portable_atomic_no_asm)),
@@ -373,11 +337,6 @@ mod atomic_128_macros {
373337
any(
374338
target_feature = "cmpxchg16b",
375339
portable_atomic_target_feature = "cmpxchg16b",
376-
all(
377-
feature = "fallback",
378-
not(portable_atomic_no_outline_atomics),
379-
not(any(target_env = "sgx", miri)),
380-
),
381340
),
382341
),
383342
all(
@@ -386,13 +345,6 @@ mod atomic_128_macros {
386345
any(
387346
target_feature = "experimental-zacas",
388347
portable_atomic_target_feature = "experimental-zacas",
389-
all(
390-
feature = "fallback",
391-
not(portable_atomic_no_outline_atomics),
392-
any(test, portable_atomic_outline_atomics), // TODO(riscv): currently disabled by default
393-
any(target_os = "linux", target_os = "android"),
394-
not(any(miri, portable_atomic_sanitize_thread)),
395-
),
396348
),
397349
),
398350
all(
@@ -401,30 +353,6 @@ mod atomic_128_macros {
401353
any(
402354
target_feature = "quadword-atomics",
403355
portable_atomic_target_feature = "quadword-atomics",
404-
all(
405-
feature = "fallback",
406-
not(portable_atomic_no_outline_atomics),
407-
any(
408-
all(
409-
target_os = "linux",
410-
any(
411-
all(
412-
target_env = "gnu",
413-
any(target_endian = "little", not(target_feature = "crt-static")),
414-
),
415-
all(
416-
any(target_env = "musl", target_env = "ohos", target_env = "uclibc"),
417-
not(target_feature = "crt-static"),
418-
),
419-
portable_atomic_outline_atomics,
420-
),
421-
),
422-
target_os = "android",
423-
target_os = "freebsd",
424-
target_os = "openbsd",
425-
),
426-
not(any(miri, portable_atomic_sanitize_thread)),
427-
),
428356
),
429357
),
430358
all(target_arch = "s390x", not(portable_atomic_no_asm)),

‎src/imp/atomic128/mod.rs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ pub(super) mod aarch64;
4646
target_os = "android",
4747
target_os = "freebsd",
4848
target_os = "openbsd",
49+
all(
50+
target_os = "aix",
51+
not(portable_atomic_pre_llvm_20),
52+
any(test, portable_atomic_outline_atomics), // TODO(aix): currently disabled by default
53+
),
4954
),
5055
not(any(miri, portable_atomic_sanitize_thread)),
5156
),

‎src/imp/atomic128/powerpc64.rs‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,19 @@ mod fallback;
7474
))]
7575
#[path = "../detect/auxv.rs"]
7676
mod detect;
77+
#[cfg(not(portable_atomic_no_outline_atomics))]
78+
#[cfg(any(
79+
test,
80+
not(any(
81+
target_feature = "quadword-atomics",
82+
portable_atomic_target_feature = "quadword-atomics",
83+
)),
84+
))]
85+
#[cfg(target_os = "aix")]
86+
#[cfg(not(portable_atomic_pre_llvm_20))] // LLVM 19 SIGILL
87+
#[cfg(any(test, portable_atomic_outline_atomics))] // TODO(aix): currently disabled by default
88+
#[path = "../detect/powerpc64_aix.rs"]
89+
mod detect;
7790

7891
use core::{arch::asm, sync::atomic::Ordering};
7992

‎src/imp/detect/README.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,18 @@ Here is the table of targets that support run-time CPU feature detection and the
1313
| aarch64 | netbsd | sysctlbyname | all | Enabled by default |
1414
| aarch64 | openbsd | sysctl | all | Enabled by default |
1515
| aarch64 | macos/ios/tvos/watchos/visionos | sysctlbyname | all | Currently only used in tests (see [aarch64_apple.rs](aarch64_apple.rs)). |
16-
| aarch64 | illumos | getisax | lse, lse2 | Disabled by default |
16+
| aarch64 | illumos | getisax | lse, lse2 | Disabled by default (experimental) |
1717
| aarch64/arm64ec | windows | IsProcessorFeaturePresent | lse | Enabled by default |
1818
| aarch64 | fuchsia | zx_system_get_features | lse | Enabled by default |
1919
| riscv32/riscv64 | linux/android | riscv_hwprobe | all | Disabled by default |
2020
| powerpc64 | linux | getauxval | all | Only enabled by default on `*-linux-{gnu,musl,ohos,uclibc}*` with dynamic linking enabled (musl is static linking by default). (dlsym is used by default if needed for compatibility with older versions) |
2121
| powerpc64 | freebsd | elf_aux_info | all | Enabled by default (dlsym is used by default for compatibility with older versions) |
2222
| powerpc64 | openbsd | elf_aux_info | all | Enabled by default (dlsym is used by default for compatibility with older versions) |
23+
| powerpc64 | aix | getsystemcfg | all | Disabled by default (experimental) |
2324

2425
Run-time detection is enabled by default on most targets and can be disabled with `--cfg portable_atomic_no_outline_atomics`.
2526

26-
On some targets, run-time detection is disabled by default mainly for incomplete build environments, and can be enabled by `--cfg portable_atomic_outline_atomics`. (When both cfg are enabled, `*_no_*` cfg is preferred.)
27+
On some targets, run-time detection is disabled by default mainly for compatibility with incomplete build environments or support for it is experimental, and can be enabled by `--cfg portable_atomic_outline_atomics`. (When both cfg are enabled, `*_no_*` cfg is preferred.)
2728

2829
For targets not included in the above table, run-time detection is always disabled and works the same as when `--cfg portable_atomic_no_outline_atomics` is set.
2930

‎src/imp/detect/aarch64_illumos.rs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ Run-time CPU feature detection on AArch64 illumos by using getisax.
66
As of nightly-2024-09-07, is_aarch64_feature_detected doesn't support run-time detection on illumos.
77
https://github.com/rust-lang/stdarch/blob/d9466edb4c53cece8686ee6e17b028436ddf4151/crates/std_detect/src/detect/mod.rs
88
9-
Run-time detection on AArch64 illumos is currently disabled by default as AArch64 port is experimental.
9+
Run-time detection on AArch64 illumos is currently disabled by default as experimental
10+
because illumos AArch64 port is experimental and we cannot run tests on the VM or real machine.
1011
*/
1112

1213
include!("common.rs");

‎src/imp/detect/powerpc64_aix.rs‎

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// SPDX-License-Identifier: Apache-2.0 OR MIT
2+
3+
/*
4+
Run-time CPU feature detection on PowerPC64 AIX by using getsystemcfg.
5+
6+
Refs:
7+
- https://github.com/golang/go/blob/071aed2aaa0ed819582c5bff44b70d43c61f504a/src/internal/cpu/cpu_ppc64x_aix.go
8+
9+
As of nightly-2024-09-07, is_powerpc_feature_detected doesn't support run-time detection on AIX.
10+
https://github.com/rust-lang/stdarch/blob/d9466edb4c53cece8686ee6e17b028436ddf4151/crates/std_detect/src/detect/mod.rs
11+
12+
Run-time detection on PowerPC64 AIX is currently disabled by default as experimental
13+
because we cannot run tests on the VM or real machine.
14+
*/
15+
16+
include!("common.rs");
17+
18+
// libc requires Rust 1.63
19+
mod ffi {
20+
pub(crate) use crate::utils::ffi::{c_int, c_ulong};
21+
22+
// TODO: use sys_const!
23+
// https://github.com/rust-lang/libc/blob/0.2.158/src/unix/aix/mod.rs#L2058
24+
// https://github.com/golang/go/blob/071aed2aaa0ed819582c5bff44b70d43c61f504a/src/internal/cpu/cpu_ppc64x_aix.go
25+
pub(crate) const SC_IMPL: c_int = 2;
26+
pub(crate) const POWER_8: c_ulong = 0x10000;
27+
pub(crate) const POWER_9: c_ulong = 0x20000;
28+
pub(crate) const POWER_10: c_ulong = 0x40000;
29+
30+
// TODO: use sys_fn!
31+
extern "C" {
32+
// https://www.ibm.com/docs/en/aix/7.3?topic=g-getsystemcfg-subroutine
33+
// https://github.com/rust-lang/libc/blob/0.2.158/src/unix/aix/powerpc64.rs#L643
34+
pub(crate) fn getsystemcfg(name: c_int) -> c_ulong;
35+
}
36+
}
37+
38+
#[cold]
39+
fn _detect(info: &mut CpuInfo) {
40+
// SAFETY: calling getsystemcfg is safe.
41+
let impl_ = unsafe { ffi::getsystemcfg(ffi::SC_IMPL) };
42+
if impl_ == ffi::c_ulong::MAX {
43+
return;
44+
}
45+
// Check both POWER_8 and later ISAs (which are superset of POWER_8) because
46+
// AIX currently doesn't set POWER_8 when POWER_9 is set.
47+
// https://github.com/golang/go/commit/51859ec2292d9c1d82a7054ec672ff551a0d7497
48+
if impl_ & (ffi::POWER_8 | ffi::POWER_9 | ffi::POWER_10) != 0 {
49+
info.set(CpuInfo::HAS_QUADWORD_ATOMICS);
50+
}
51+
}
52+
53+
#[allow(
54+
clippy::alloc_instead_of_core,
55+
clippy::std_instead_of_alloc,
56+
clippy::std_instead_of_core,
57+
clippy::undocumented_unsafe_blocks,
58+
clippy::wildcard_imports
59+
)]
60+
#[cfg(test)]
61+
mod tests {
62+
use super::*;
63+
64+
// Static assertions for FFI bindings.
65+
// This checks that FFI bindings defined in this crate and FFI bindings defined
66+
// in libc compatible signatures (or the same values if constants).
67+
// Since this is static assertion, we can detect problems with
68+
// `cargo check --tests --target <target>` run in CI (via TESTS=1 build.sh)
69+
// without actually running tests on these platforms.
70+
// See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs.
71+
// TODO: auto-generate this test
72+
#[allow(
73+
clippy::cast_possible_wrap,
74+
clippy::cast_sign_loss,
75+
clippy::cast_possible_truncation,
76+
clippy::no_effect_underscore_binding
77+
)]
78+
const _: fn() = || {
79+
use test_helper::libc;
80+
let mut _getsystemcfg: unsafe extern "C" fn(ffi::c_int) -> ffi::c_ulong = ffi::getsystemcfg;
81+
_getsystemcfg = libc::getsystemcfg;
82+
static_assert!(ffi::SC_IMPL == libc::SC_IMPL);
83+
static_assert!(ffi::POWER_8 == libc::POWER_8 as ffi::c_ulong);
84+
static_assert!(ffi::POWER_9 == libc::POWER_9 as ffi::c_ulong);
85+
// static_assert!(ffi::POWER_10 == libc::POWER_10 as ffi::c_ulong); // libc doesn't have this
86+
};
87+
}

‎src/imp/fallback/mod.rs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ type and the value type must be the same.
4242
target_os = "android",
4343
target_os = "freebsd",
4444
target_os = "openbsd",
45+
all(
46+
target_os = "aix",
47+
not(portable_atomic_pre_llvm_20),
48+
portable_atomic_outline_atomics, // TODO(aix): currently disabled by default
49+
),
4550
),
4651
not(any(miri, portable_atomic_sanitize_thread)),
4752
),

0 commit comments

Comments
 (0)