[glibc] riscv: Add RVV strncpy for both multiarch and non-multiarch builds
Peter Bergner via Glibc-cvs <[email protected]> Sun, 5 Jul 2026 13:38:11 +0000 (GMT)
| Newsgroups | gmane.comp.lib.glibc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=59cb960a22fbacb8b8baaa049529bf4638dfc625 commit 59cb960a22fbacb8b8baaa049529bf4638dfc625 Author: Yao Zihong <[email protected]> Date: Fri Jul 3 21:59:53 2026 +0000 riscv: Add RVV strncpy for both multiarch and non-multiarch builds This patch adds an RVV-optimized implementation of strncpy for RISC-V and enables it for both multiarch (IFUNC) and non-multiarch builds. The implementation integrates Hau Hsu's 2023 RVV work under a unified ifunc-based framework. A vectorized version (__strncpy_vector) is added alongside the generic fallback (__strncpy_generic). The runtime resolver selects the RVV variant when RISCV_HWPROBE_KEY_IMA_EXT_0 reports vector support (RVV). Currently, the resolver still selects the RVV variant even when the RVV extension is disabled via prctl(). As a consequence, any process that has RVV disabled via prctl() will receive SIGILL when calling strncpy(). Co-authored-by: Hau Hsu <[email protected]> Co-authored-by: Jerry Shih <[email protected]> Signed-off-by: Yao Zihong <[email protected]> Reviewed-by: Peter Bergner <[email protected]> Diff: --- sysdeps/riscv/multiarch/strncpy-generic.c | 26 ++++++++++ sysdeps/riscv/multiarch/strncpy-vector.S | 24 +++++++++ sysdeps/riscv/rvv/stpncpy.S | 27 ++++++++-- sysdeps/riscv/rvv/strncpy.S | 20 ++++++++ sysdeps/unix/sysv/linux/riscv/multiarch/Makefile | 3 ++ .../sysv/linux/riscv/multiarch/ifunc-impl-list.c | 5 ++ sysdeps/unix/sysv/linux/riscv/multiarch/strncpy.c | 59 ++++++++++++++++++++++ 7 files changed, 159 insertions(+), 5 deletions(-) diff --git a/sysdeps/riscv/multiarch/strncpy-generic.c b/sysdeps/riscv/multiarch/strncpy-generic.c new file mode 100644 index 0000000000..726ca9ed5f --- /dev/null +++ b/sysdeps/riscv/multiarch/strncpy-generic.c @@ -0,0 +1,26 @@ +/* Re-include the default strncpy implementation. + Copyright (C) 2026 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <string.h> + +#if IS_IN(libc) +# define STRNCPY __strncpy_generic +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(x) +# include <string/strncpy.c> +#endif diff --git a/sysdeps/riscv/multiarch/strncpy-vector.S b/sysdeps/riscv/multiarch/strncpy-vector.S new file mode 100644 index 0000000000..32256f7695 --- /dev/null +++ b/sysdeps/riscv/multiarch/strncpy-vector.S @@ -0,0 +1,24 @@ +/* Re-include the RISC-V RVV based strncpy implementation. + Copyright (C) 2026 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#if IS_IN(libc) +# define STRNCPY __strncpy_vector +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(x) +# include <sysdeps/riscv/rvv/strncpy.S> +#endif diff --git a/sysdeps/riscv/rvv/stpncpy.S b/sysdeps/riscv/rvv/stpncpy.S index 7cfc2f76cc..71bb46b04e 100644 --- a/sysdeps/riscv/rvv/stpncpy.S +++ b/sysdeps/riscv/rvv/stpncpy.S @@ -19,12 +19,20 @@ #include <sysdep.h> #include <sys/asm.h> -#ifndef STPNCPY -# ifdef weak_alias -# define STPNCPY __stpncpy +#ifndef USE_AS_STRNCPY +# ifndef STPNCPY +# ifdef weak_alias +# define STPNCPY __stpncpy weak_alias (__stpncpy, stpncpy) +# else +# define STPNCPY stpncpy +# endif +# endif +#else +# ifndef STRNCPY +# define STPNCPY strncpy # else -# define STPNCPY stpncpy +# define STPNCPY STRNCPY # endif #endif @@ -62,7 +70,9 @@ L(stpcpy_loop): add dst_ptr, dst_ptr, cur_vl bgez active_elem_pos, L(fill_zero) bnez length, L(stpcpy_loop) +#ifndef USE_AS_STRNCPY mv dst, dst_ptr +#endif ret /* Fill the tail zero. */ @@ -72,8 +82,10 @@ L(fill_zero): to get the correct remaining length for zero filling. */ sub temp, cur_vl, active_elem_pos addi temp, temp, -1 +#ifndef USE_AS_STRNCPY sub dst, dst_ptr, cur_vl add dst, dst, active_elem_pos +#endif add length, length, temp /* Return early for the `strlen(src) + 1 == count` case. */ bnez length, L(do_fill_zero) @@ -92,6 +104,11 @@ L(fill_zero_loop): ret .option pop END (STPNCPY) -#ifdef weak_alias + +#ifndef USE_AS_STRNCPY +# ifdef weak_alias libc_hidden_def (__stpncpy) +# endif +#else +libc_hidden_builtin_def (strncpy) #endif diff --git a/sysdeps/riscv/rvv/strncpy.S b/sysdeps/riscv/rvv/strncpy.S new file mode 100644 index 0000000000..961c16416e --- /dev/null +++ b/sysdeps/riscv/rvv/strncpy.S @@ -0,0 +1,20 @@ +/* RISC-V RVV based strncpy. + Copyright (C) 2026 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#define USE_AS_STRNCPY +#include <sysdeps/riscv/rvv/stpncpy.S> diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile b/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile index 25d8216d2e..4991466369 100644 --- a/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile +++ b/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile @@ -40,6 +40,9 @@ sysdep_routines += \ strncmp \ strncmp-generic \ strncmp-vector \ + strncpy \ + strncpy-generic \ + strncpy-vector \ strrchr \ strrchr-generic \ strrchr-vector \ diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c b/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c index 755ba9d637..ac2b25de74 100644 --- a/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c +++ b/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c @@ -115,5 +115,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, __stpncpy_vector) IFUNC_IMPL_ADD (array, i, stpncpy, 1, __stpncpy_generic)) + IFUNC_IMPL (i, name, strncpy, + IFUNC_IMPL_ADD (array, i, strncpy, rvv_enabled, + __strncpy_vector) + IFUNC_IMPL_ADD (array, i, strncpy, 1, __strncpy_generic)) + return 0; } diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/strncpy.c b/sysdeps/unix/sysv/linux/riscv/multiarch/strncpy.c new file mode 100644 index 0000000000..2ed6878bfd --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/multiarch/strncpy.c @@ -0,0 +1,59 @@ +/* Multiple versions of strncpy. + All versions must be listed in ifunc-impl-list.c. + Copyright (C) 2026 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#if IS_IN (libc) +#define SYMBOL_NAME strncpy +# include <ifunc-init.h> + +/* Redefine strncpy so that the compiler won't complain about the type + mismatch with the IFUNC selector in strong_alias, below. */ +# undef strncpy +# define strncpy REDIRECT_NAME +# include <string.h> +# undef strncpy + +# include <stdint.h> +# include <riscv-ifunc.h> +# include <sys/hwprobe.h> + +extern __typeof (REDIRECT_NAME) __strncpy; +extern __typeof (REDIRECT_NAME) OPTIMIZE (generic) attribute_hidden; +extern __typeof (REDIRECT_NAME) OPTIMIZE (vector) attribute_hidden; + +static inline __typeof (REDIRECT_NAME) * +select_strncpy_ifunc (uint64_t dl_hwcap, __riscv_hwprobe_t hwprobe_func) +{ + unsigned long long int v; + if (__riscv_hwprobe_one (hwprobe_func, RISCV_HWPROBE_KEY_IMA_EXT_0, &v) == 0 + && (v & RISCV_HWPROBE_IMA_V) == RISCV_HWPROBE_IMA_V) + return OPTIMIZE (vector); + return OPTIMIZE (generic); +} + +riscv_libc_ifunc (__strncpy, select_strncpy_ifunc); + +strong_alias (__strncpy, strncpy); + +# ifdef SHARED +__hidden_ver1 (strncpy, __GI_strncpy, REDIRECT_NAME) + __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strncpy); +# endif +#else +# include <string/strncpy.c> +#endif