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

Reply via email to