https://gcc.gnu.org/g:1e819a997dd5507e52cafc540656fc15160322fd
commit r15-7294-g1e819a997dd5507e52cafc540656fc15160322fd Author: Georg-Johann Lay <a...@gjlay.de> Date: Thu Jan 30 12:16:50 2025 +0100 AVR: Provide built-ins for strlen where the string lives in some AS. This patch adds built-in functions __builtin_avr_strlen_flash, __builtin_avr_strlen_flashx and __builtin_avr_strlen_memx. Purpose is that higher-level functions can use __builtin_constant_p on strlen without raising a diagnostic due to -Waddr-space-convert. gcc/ * config/avr/builtins.def (STRLEN_FLASH, STRLEN_FLASHX) (STRLEN_MEMX): New DEF_BUILTIN's. * config/avr/avr.cc (avr_ftype_strlen): New static function. (avr_builtin_supported_p): New built-ins are not for AVR_TINY. (avr_init_builtins) <strlen_flash_node, strlen_flashx_node, strlen_memx_node>: Provide new fntypes. (avr_fold_builtin) [AVR_BUILTIN_STRLEN_FLASH] [AVR_BUILTIN_STRLEN_FLASHX, AVR_BUILTIN_STRLEN_MEMX]: Fold if possible. * doc/extend.texi (AVR Built-in Functions): Document __builtin_avr_strlen_flash, __builtin_avr_strlen_flashx, __builtin_avr_strlen_memx. libgcc/ * config/avr/t-avr (LIB1ASMFUNCS): Add _strlen_memx. * config/avr/lib1funcs.S <L_strlen_memx, __strlen_memx>: Implement. Diff: --- gcc/config/avr/avr.cc | 35 ++++++++++++++++++++++++++++++++++- gcc/config/avr/builtins.def | 6 ++++++ gcc/doc/extend.texi | 10 ++++++++++ libgcc/config/avr/lib1funcs.S | 18 ++++++++++++++++++ libgcc/config/avr/t-avr | 3 ++- 5 files changed, 70 insertions(+), 2 deletions(-) diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index 2b550e7761c8..9454cb933d7c 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -15696,7 +15696,10 @@ avr_bdesc[AVR_BUILTIN_COUNT] = bool avr_builtin_supported_p (unsigned id) { - const bool uses_as = id == AVR_BUILTIN_FLASH_SEGMENT; + const bool uses_as = (id == AVR_BUILTIN_FLASH_SEGMENT + || id == AVR_BUILTIN_STRLEN_FLASH + || id == AVR_BUILTIN_STRLEN_FLASHX + || id == AVR_BUILTIN_STRLEN_MEMX); // We don't support address-spaces on Reduced Tiny. if (AVR_TINY && uses_as) @@ -15732,6 +15735,25 @@ avr_init_builtin_int24 (void) } +/* Return a function signature type similar to strlen, but where + the address is qualified by named address-space AS. */ + +static tree +avr_ftype_strlen (addr_space_t as) +{ + tree const_AS_char_node + = build_qualified_type (char_type_node, + TYPE_QUAL_CONST | ENCODE_QUAL_ADDR_SPACE (as)); + tree const_AS_ptr_type_node + = build_pointer_type_for_mode (const_AS_char_node, + avr_addr_space_pointer_mode (as), false); + tree size_ftype_const_AS_char_ptr + = build_function_type_list (size_type_node, const_AS_ptr_type_node, NULL); + + return size_ftype_const_AS_char_ptr; +} + + /* Implement `TARGET_INIT_BUILTINS' */ /* Set up all builtin functions for this target. */ @@ -15789,6 +15811,10 @@ avr_init_builtins (void) const_memx_ptr_type_node, NULL); + tree strlen_flash_node = avr_ftype_strlen (ADDR_SPACE_FLASH); + tree strlen_flashx_node = avr_ftype_strlen (ADDR_SPACE_FLASHX); + tree strlen_memx_node = avr_ftype_strlen (ADDR_SPACE_MEMX); + #define ITYP(T) \ lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T)) @@ -16180,6 +16206,13 @@ avr_fold_builtin (tree fndecl, int /*n_args*/, tree *arg, bool /*ignore*/) build_int_cst (val_type, 4)); } + case AVR_BUILTIN_STRLEN_FLASH: + case AVR_BUILTIN_STRLEN_FLASHX: + case AVR_BUILTIN_STRLEN_MEMX: + if (tree len = c_strlen (arg[0], 0)) + return len; + break; + case AVR_BUILTIN_ABSHR: case AVR_BUILTIN_ABSR: case AVR_BUILTIN_ABSLR: diff --git a/gcc/config/avr/builtins.def b/gcc/config/avr/builtins.def index ad75fe9c267c..c96108977844 100644 --- a/gcc/config/avr/builtins.def +++ b/gcc/config/avr/builtins.def @@ -65,6 +65,12 @@ DEF_BUILTIN (INSERT_BITS, 3, uintQI_ftype_uintSI_uintQI_uintQI, insert_bits, NUL DEF_BUILTIN (FLASH_SEGMENT, 1, intQI_ftype_const_memx_ptr, flash_segment, NULL, attr_const) +/* strlen for ASes so that __builtin_constant_p can be used wthout raising + a diagnostic from -Waddr-space-convert in some AVR-LibC headers. */ +DEF_BUILTIN (STRLEN_FLASH, 1, strlen_flash_node, nothing, "__strlen_P", attr_const) // AVR-LibC +DEF_BUILTIN (STRLEN_FLASHX, 1, strlen_flashx_node, nothing, "strlen_PF", attr_const) // AVR-LibC +DEF_BUILTIN (STRLEN_MEMX, 1, strlen_memx_node, nothing, "__strlen_memx", NULL_TREE) + /* ISO/IEC TR 18037 "Embedded C" The following builtins are undocumented and used by stdfix.h. */ diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index c6e7bc37f7dc..d79e97d9a030 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -17447,6 +17447,16 @@ points to. Counting starts at @code{0}. If the address does not point to flash memory, return @code{-1}. @enddefbuiltin +@defbuiltin{size_t __builtin_avr_strlen_flash (const __flash char*)} +@defbuiltinx{size_t __builtin_avr_strlen_flashx (const __flashx char*)} +@defbuiltinx{size_t __builtin_avr_strlen_memx (const __memx char*)} +These built-ins return the length of a string located in +named address-space @code{__flash}, @code{__flashx} or @code{__memx}, +respectively. They are used to support functions like @code{strlen_F} from +@w{@uref{https://avrdudes.github.io/avr-libc/avr-libc-user-manual/,AVR-LibC}}'s +header @code{avr/flash.h}. +@enddefbuiltin + @noindent There are many more AVR-specific built-in functions that are used to implement the ISO/IEC TR 18037 ``Embedded C'' fixed-point functions of diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S index 580f511eb94c..96f20ca8e646 100644 --- a/libgcc/config/avr/lib1funcs.S +++ b/libgcc/config/avr/lib1funcs.S @@ -2755,6 +2755,24 @@ ENDF __fload_4 #endif /* L_fload_{1|2|3|4} */ #endif /* if !defined (__AVR_TINY__) */ + +#if !defined (__AVR_TINY__) +#if defined (L_strlen_memx) +DEFUN __strlen_memx +#ifdef __AVR_ERRATA_SKIP_JMP_CALL__ + tst r24 + brmi 1f +#else + sbrs r24, 7 +#endif + XJMP strlen_PF ; AVR-LibC +1: wmov 24, 22 + XJMP strlen ; AVR-LibC +ENDF __strlen_memx +#endif /* L_strlen_memx */ +#endif /* if !defined (__AVR_TINY__) */ + + #if !defined (__AVR_TINY__) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; memcopy from Address Space __memx to RAM diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr index e9fdb98d7765..f98d48fc013e 100644 --- a/libgcc/config/avr/t-avr +++ b/libgcc/config/avr/t-avr @@ -33,7 +33,8 @@ LIB1ASMFUNCS = \ _popcountsi2 \ _popcountqi2 \ _bswapsi2 \ - _fmul _fmuls _fmulsu + _fmul _fmuls _fmulsu \ + _strlen_memx # The below functions either use registers that are not present # in tiny core, or use a different register convention (don't save