From 000763f8db56489321158581cf759ccbf97de8d8 Mon Sep 17 00:00:00 2001 From: Tsukasa OI Date: Sun, 14 Sep 2025 04:37:45 +0000 Subject: [PATCH 1/2] RISC-V: Add virtual target feature: `zkne_or_zknd` Because some AES key scheduling instructions require *either* Zkne or Zknd extension, we must have a target feature to represent `(Zkne || Zknd)`. This commit adds (perma-unstable) target feature to the RISC-V architecture: `zkne_or_zknd` for this purpose. Helped-by: sayantn --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 2 ++ compiler/rustc_target/src/target_features.rs | 5 +++-- tests/ui/check-cfg/target_feature.stderr | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 45c5c9aa5514d..1e7f55c802038 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -251,6 +251,8 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option None, ("powerpc", "power8-crypto") => Some(LLVMFeature::new("crypto")), + // Filter out Rust-specific *virtual* target features + ("riscv32" | "riscv64", "zkne_or_zknd") => None, ("sparc", "leoncasa") => Some(LLVMFeature::new("hasleoncasa")), ("x86", "sse4.2") => Some(LLVMFeature::with_dependencies( "sse4.2", diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index dc70089c385fe..c5cb03eea8e27 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -691,8 +691,9 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("zimop", Unstable(sym::riscv_target_feature), &[]), ("zk", Stable, &["zkn", "zkr", "zkt"]), ("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]), - ("zknd", Stable, &[]), - ("zkne", Stable, &[]), + ("zknd", Stable, &["zkne_or_zknd"]), + ("zkne", Stable, &["zkne_or_zknd"]), + ("zkne_or_zknd", Unstable(sym::riscv_target_feature), &[]), // Not an extension ("zknh", Stable, &[]), ("zkr", Stable, &[]), ("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]), diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 258f21324661b..1e92c07481b95 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -424,6 +424,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `zkn` `zknd` `zkne` +`zkne_or_zknd` `zknh` `zkr` `zks` From 84fc8a66fb2a2ebd8983544c862fdbd02a6c3fba Mon Sep 17 00:00:00 2001 From: Tsukasa OI Date: Fri, 19 Sep 2025 21:36:50 +0000 Subject: [PATCH 2/2] RISC-V: Use inline assembly and `zkne_or_zknd` on (Zkne or Zknd) intrinsics Using the inline assembly and `zkne_or_zknd` target feature could avoid current issues regarding intrinsics available when either Zkne or Zknd is available. Before this commit, intrinsics `aes64ks1i` and `aes64ks2` required both Zkne and Zknd extensions, not either Zkne or Zknd. Closes: https://github.com/rust-lang/stdarch/issues/1765 --- .../crates/core_arch/src/riscv64/zk.rs | 45 +++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/riscv64/zk.rs b/library/stdarch/crates/core_arch/src/riscv64/zk.rs index a30653cbe0885..3aa1ca39b3c94 100644 --- a/library/stdarch/crates/core_arch/src/riscv64/zk.rs +++ b/library/stdarch/crates/core_arch/src/riscv64/zk.rs @@ -1,6 +1,8 @@ #[cfg(test)] use stdarch_test::assert_instr; +use crate::arch::asm; + unsafe extern "unadjusted" { #[link_name = "llvm.riscv.aes64es"] fn _aes64es(rs1: i64, rs2: i64) -> i64; @@ -14,12 +16,6 @@ unsafe extern "unadjusted" { #[link_name = "llvm.riscv.aes64dsm"] fn _aes64dsm(rs1: i64, rs2: i64) -> i64; - #[link_name = "llvm.riscv.aes64ks1i"] - fn _aes64ks1i(rs1: i64, rnum: i32) -> i64; - - #[link_name = "llvm.riscv.aes64ks2"] - fn _aes64ks2(rs1: i64, rs2: i64) -> i64; - #[link_name = "llvm.riscv.aes64im"] fn _aes64im(rs1: i64) -> i64; @@ -133,15 +129,26 @@ pub fn aes64dsm(rs1: u64, rs2: u64) -> u64 { /// # Note /// /// The `RNUM` parameter is expected to be a constant value inside the range of `0..=10`. -#[target_feature(enable = "zkne", enable = "zknd")] +#[target_feature(enable = "zkne_or_zknd")] #[rustc_legacy_const_generics(1)] -#[cfg_attr(test, assert_instr(aes64ks1i, RNUM = 0))] #[inline] #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")] pub fn aes64ks1i(rs1: u64) -> u64 { static_assert!(RNUM <= 10); - - unsafe { _aes64ks1i(rs1 as i64, RNUM as i32) as u64 } + unsafe { + let rd: u64; + asm!( + ".option push", + ".option arch, +zkne", + "aes64ks1i {}, {}, {}", + ".option pop", + lateout(reg) rd, + in(reg) rs1, + const RNUM, + options(pure, nomem, nostack, preserves_flags) + ); + rd + } } /// This instruction implements part of the KeySchedule operation for the AES Block cipher. @@ -155,12 +162,24 @@ pub fn aes64ks1i(rs1: u64) -> u64 { /// Version: v1.0.1 /// /// Section: 3.11 -#[target_feature(enable = "zkne", enable = "zknd")] -#[cfg_attr(test, assert_instr(aes64ks2))] +#[target_feature(enable = "zkne_or_zknd")] #[inline] #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")] pub fn aes64ks2(rs1: u64, rs2: u64) -> u64 { - unsafe { _aes64ks2(rs1 as i64, rs2 as i64) as u64 } + unsafe { + let rd: u64; + asm!( + ".option push", + ".option arch, +zkne", + "aes64ks2 {}, {}, {}", + ".option pop", + lateout(reg) rd, + in(reg) rs1, + in(reg) rs2, + options(pure, nomem, nostack, preserves_flags) + ); + rd + } } /// This instruction accelerates the inverse MixColumns step of the AES Block Cipher, and is used to aid creation of