From 6ff8b9b94ee7c6935fb8598a61d8a6d81b094bda Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 6 Mar 2026 21:26:59 +0100 Subject: [PATCH 1/3] add ACLE random number generation intrinsics --- crates/core_arch/src/aarch64/mod.rs | 4 ++ crates/core_arch/src/aarch64/rand.rs | 69 ++++++++++++++++++++++++++++ crates/stdarch-verify/tests/arm.rs | 1 + 3 files changed, 74 insertions(+) create mode 100644 crates/core_arch/src/aarch64/rand.rs diff --git a/crates/core_arch/src/aarch64/mod.rs b/crates/core_arch/src/aarch64/mod.rs index b48bdac57e..d7295659c3 100644 --- a/crates/core_arch/src/aarch64/mod.rs +++ b/crates/core_arch/src/aarch64/mod.rs @@ -17,6 +17,10 @@ mod mte; #[unstable(feature = "stdarch_aarch64_mte", issue = "129010")] pub use self::mte::*; +mod rand; +#[unstable(feature = "stdarch_aarch64_rand", issue = "153514")] +pub use self::rand::*; + mod neon; #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub use self::neon::*; diff --git a/crates/core_arch/src/aarch64/rand.rs b/crates/core_arch/src/aarch64/rand.rs new file mode 100644 index 0000000000..5492fd0144 --- /dev/null +++ b/crates/core_arch/src/aarch64/rand.rs @@ -0,0 +1,69 @@ +//! AArch64 Random Number intrinsics +//! +//! [ACLE documentation](https://arm-software.github.io/acle/main/acle.html#random-number-generation-intrinsics) + +unsafe extern "unadjusted" { + #[cfg_attr( + any(target_arch = "aarch64", target_arch = "arm64ec"), + link_name = "llvm.aarch64.rndr" + )] + fn rndr_() -> Tuple; + + #[cfg_attr( + any(target_arch = "aarch64", target_arch = "arm64ec"), + link_name = "llvm.aarch64.rndrrs" + )] + fn rndrrs_() -> Tuple; +} + +#[repr(C)] +struct Tuple { + bits: u64, + status: bool, +} + +/// Stores a 64-bit random number into the object pointed to by the argument and returns +/// zero. If the implementation could not generate a random number within a reasonable +/// period of time the object pointed to by the input is set to zero and a non-zero value +/// is returned. +#[inline] +#[target_feature(enable = "rand")] +#[unstable(feature = "stdarch_aarch64_rand", issue = "153514")] +pub unsafe fn __rndr(value: *mut u64) -> i32 { + let Tuple { bits, status } = rndr_(); + unsafe { *value = bits }; + status as i32 +} + +/// Reseeds the random number generator. After that stores a 64-bit random number into +/// the object pointed to by the argument and returns zero. If the implementation could +/// not generate a random number within a reasonable period of time the object pointed +/// to by the input is set to zero and a non-zero value is returned. +#[inline] +#[target_feature(enable = "rand")] +#[unstable(feature = "stdarch_aarch64_rand", issue = "153514")] +pub unsafe fn __rndrrs(value: *mut u64) -> i32 { + let Tuple { bits, status } = rndrrs_(); + unsafe { *value = bits }; + status as i32 +} + +#[cfg(test)] +mod test { + use super::*; + use stdarch_test::assert_instr; + + #[cfg_attr(test, assert_instr(mrs))] + #[allow(dead_code)] + #[target_feature(enable = "rand")] + unsafe fn test_rndr(value: &mut u64) -> i32 { + __rndr(value) + } + + #[cfg_attr(test, assert_instr(mrs))] + #[allow(dead_code)] + #[target_feature(enable = "rand")] + unsafe fn test_rndrrs(value: &mut u64) -> i32 { + __rndrrs(value) + } +} diff --git a/crates/stdarch-verify/tests/arm.rs b/crates/stdarch-verify/tests/arm.rs index 86897908e0..3ef9ce2a38 100644 --- a/crates/stdarch-verify/tests/arm.rs +++ b/crates/stdarch-verify/tests/arm.rs @@ -445,6 +445,7 @@ fn verify_all_signatures() { && !rust.file.ends_with("v7.rs\"") && !rust.file.ends_with("v8.rs\"") && !rust.file.ends_with("mte.rs\"") + && !rust.file.ends_with("rand.rs\"") && !rust.file.ends_with("ex.rs\"") && !skip_intrinsic_verify.contains(&rust.name) { From 44f40691ddf205368ef5809cd7d41da1486e428e Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 12 Mar 2026 10:37:52 +0100 Subject: [PATCH 2/3] remove `cfg_attr` on `aarch64`/`arm64ec` in the aarch64 module --- crates/core_arch/src/aarch64/mte.rs | 30 ++++++---------------------- crates/core_arch/src/aarch64/rand.rs | 10 ++-------- 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/crates/core_arch/src/aarch64/mte.rs b/crates/core_arch/src/aarch64/mte.rs index c400f774bc..1b05eb3498 100644 --- a/crates/core_arch/src/aarch64/mte.rs +++ b/crates/core_arch/src/aarch64/mte.rs @@ -3,35 +3,17 @@ //! [ACLE documentation](https://arm-software.github.io/acle/main/acle.html#markdown-toc-mte-intrinsics) unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.irg" - )] + #[link_name = "llvm.aarch64.irg"] fn irg_(ptr: *const (), exclude: i64) -> *const (); - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.gmi" - )] + #[link_name = "llvm.aarch64.gmi"] fn gmi_(ptr: *const (), exclude: i64) -> i64; - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.ldg" - )] + #[link_name = "llvm.aarch64.ldg"] fn ldg_(ptr: *const (), tag_ptr: *const ()) -> *const (); - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.stg" - )] + #[link_name = "llvm.aarch64.stg"] fn stg_(tagged_ptr: *const (), addr_to_tag: *const ()); - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.addg" - )] + #[link_name = "llvm.aarch64.addg"] fn addg_(ptr: *const (), value: i64) -> *const (); - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.subp" - )] + #[link_name = "llvm.aarch64.subp"] fn subp_(ptr_a: *const (), ptr_b: *const ()) -> i64; } diff --git a/crates/core_arch/src/aarch64/rand.rs b/crates/core_arch/src/aarch64/rand.rs index 5492fd0144..17b616f4ec 100644 --- a/crates/core_arch/src/aarch64/rand.rs +++ b/crates/core_arch/src/aarch64/rand.rs @@ -3,16 +3,10 @@ //! [ACLE documentation](https://arm-software.github.io/acle/main/acle.html#random-number-generation-intrinsics) unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.rndr" - )] + #[link_name = "llvm.aarch64.rndr"] fn rndr_() -> Tuple; - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.rndrrs" - )] + #[link_name = "llvm.aarch64.rndrrs"] fn rndrrs_() -> Tuple; } From d6ffea0306966691ddcab4b232085e09bb76eb58 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 12 Mar 2026 12:32:35 +0100 Subject: [PATCH 3/3] inline `assert_instr` tests --- crates/core_arch/src/aarch64/mte.rs | 16 ++++++++++------ crates/core_arch/src/aarch64/rand.rs | 25 +++++-------------------- 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/crates/core_arch/src/aarch64/mte.rs b/crates/core_arch/src/aarch64/mte.rs index 1b05eb3498..a5031a45c1 100644 --- a/crates/core_arch/src/aarch64/mte.rs +++ b/crates/core_arch/src/aarch64/mte.rs @@ -109,42 +109,46 @@ mod test { use super::*; use stdarch_test::assert_instr; - #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(irg))] // FIXME: MSVC `dumpbin` doesn't support MTE + // Instruction tests are separate because the functions use generics. + // + // FIXME: As of 2026 MSVC `dumpbin` doesn't support MTE. + + #[cfg_attr(not(target_env = "msvc"), assert_instr(irg))] #[allow(dead_code)] #[target_feature(enable = "mte")] unsafe fn test_arm_mte_create_random_tag(src: *const (), mask: u64) -> *const () { __arm_mte_create_random_tag(src, mask) } - #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(addg))] + #[cfg_attr(not(target_env = "msvc"), assert_instr(addg))] #[allow(dead_code)] #[target_feature(enable = "mte")] unsafe fn test_arm_mte_increment_tag(src: *const ()) -> *const () { __arm_mte_increment_tag::<1, _>(src) } - #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(gmi))] + #[cfg_attr(not(target_env = "msvc"), assert_instr(gmi))] #[allow(dead_code)] #[target_feature(enable = "mte")] unsafe fn test_arm_mte_exclude_tag(src: *const (), excluded: u64) -> u64 { __arm_mte_exclude_tag(src, excluded) } - #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stg))] + #[cfg_attr(not(target_env = "msvc"), assert_instr(stg))] #[allow(dead_code)] #[target_feature(enable = "mte")] unsafe fn test_arm_mte_set_tag(src: *const ()) { __arm_mte_set_tag(src) } - #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldg))] + #[cfg_attr(not(target_env = "msvc"), assert_instr(ldg))] #[allow(dead_code)] #[target_feature(enable = "mte")] unsafe fn test_arm_mte_get_tag(src: *const ()) -> *const () { __arm_mte_get_tag(src) } - #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(subp))] + #[cfg_attr(not(target_env = "msvc"), assert_instr(subp))] #[allow(dead_code)] #[target_feature(enable = "mte")] unsafe fn test_arm_mte_ptrdiff(a: *const (), b: *const ()) -> i64 { diff --git a/crates/core_arch/src/aarch64/rand.rs b/crates/core_arch/src/aarch64/rand.rs index 17b616f4ec..3f52cf2ce8 100644 --- a/crates/core_arch/src/aarch64/rand.rs +++ b/crates/core_arch/src/aarch64/rand.rs @@ -2,6 +2,9 @@ //! //! [ACLE documentation](https://arm-software.github.io/acle/main/acle.html#random-number-generation-intrinsics) +#[cfg(test)] +use stdarch_test::assert_instr; + unsafe extern "unadjusted" { #[link_name = "llvm.aarch64.rndr"] fn rndr_() -> Tuple; @@ -22,6 +25,7 @@ struct Tuple { /// is returned. #[inline] #[target_feature(enable = "rand")] +#[cfg_attr(test, assert_instr(mrs))] #[unstable(feature = "stdarch_aarch64_rand", issue = "153514")] pub unsafe fn __rndr(value: *mut u64) -> i32 { let Tuple { bits, status } = rndr_(); @@ -35,29 +39,10 @@ pub unsafe fn __rndr(value: *mut u64) -> i32 { /// to by the input is set to zero and a non-zero value is returned. #[inline] #[target_feature(enable = "rand")] +#[cfg_attr(test, assert_instr(mrs))] #[unstable(feature = "stdarch_aarch64_rand", issue = "153514")] pub unsafe fn __rndrrs(value: *mut u64) -> i32 { let Tuple { bits, status } = rndrrs_(); unsafe { *value = bits }; status as i32 } - -#[cfg(test)] -mod test { - use super::*; - use stdarch_test::assert_instr; - - #[cfg_attr(test, assert_instr(mrs))] - #[allow(dead_code)] - #[target_feature(enable = "rand")] - unsafe fn test_rndr(value: &mut u64) -> i32 { - __rndr(value) - } - - #[cfg_attr(test, assert_instr(mrs))] - #[allow(dead_code)] - #[target_feature(enable = "rand")] - unsafe fn test_rndrrs(value: &mut u64) -> i32 { - __rndrrs(value) - } -}