OSDN Git Service

gcc:
authorghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 13 Apr 2003 23:46:11 +0000 (23:46 +0000)
committerghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 13 Apr 2003 23:46:11 +0000 (23:46 +0000)
* builtins.c (expand_builtin_memcpy): Add `endp' argument, use it.
(expand_builtin_stpcpy): New.
(expand_builtin): Add BUILT_IN_MEMPCPY & BUILT_IN_STPCPY.
* builtins.def: Add mempcpy & stpcpy support.
* doc/extend.texi (mempcpy, stpcpy): Document new builtins.

testsuite:
* gcc.c-torture/execute/string-opt-18.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@65551 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/builtins.c
gcc/builtins.def
gcc/doc/extend.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/string-opt-18.c [new file with mode: 0644]

index c6a5117..25c09aa 100644 (file)
@@ -1,3 +1,11 @@
+2003-04-13  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * builtins.c (expand_builtin_memcpy): Add `endp' argument, use it.
+       (expand_builtin_stpcpy): New.
+       (expand_builtin): Add BUILT_IN_MEMPCPY & BUILT_IN_STPCPY.
+       * builtins.def: Add mempcpy & stpcpy support.
+       * doc/extend.texi (mempcpy, stpcpy): Document new builtins.
+
 2003-04-13  Nick Clifton  <nickc@redhat.com>
 
        * config/rs6000/rs6000.c: Replace occurrences of "GNU CC" with
index 667de5f..51e8976 100644 (file)
@@ -125,9 +125,11 @@ static rtx expand_builtin_strspn   PARAMS ((tree, rtx,
 static rtx expand_builtin_strcspn      PARAMS ((tree, rtx,
                                                 enum machine_mode));
 static rtx expand_builtin_memcpy       PARAMS ((tree, rtx,
-                                                enum machine_mode));
+                                                enum machine_mode, int));
 static rtx expand_builtin_strcpy       PARAMS ((tree, rtx,
                                                 enum machine_mode));
+static rtx expand_builtin_stpcpy       PARAMS ((tree, rtx,
+                                                enum machine_mode));
 static rtx builtin_strncpy_read_str    PARAMS ((PTR, HOST_WIDE_INT,
                                                 enum machine_mode));
 static rtx expand_builtin_strncpy      PARAMS ((tree, rtx,
@@ -2252,15 +2254,18 @@ builtin_memcpy_read_str (data, offset, mode)
 }
 
 /* Expand a call to the memcpy builtin, with arguments in ARGLIST.
-   Return 0 if we failed, the caller should emit a normal call, otherwise
-   try to get the result in TARGET, if convenient (and in mode MODE if
-   that's convenient).  */
-
+   Return 0 if we failed, the caller should emit a normal call,
+   otherwise try to get the result in TARGET, if convenient (and in
+   mode MODE if that's convenient).  If ENDP is 0 return the
+   destination pointer, if ENDP is 1 return the end pointer ala
+   mempcpy, and if ENDP is 2 return the end pointer minus one ala
+   stpcpy.  */
 static rtx
-expand_builtin_memcpy (arglist, target, mode)
+expand_builtin_memcpy (arglist, target, mode, endp)
      tree arglist;
      rtx target;
      enum machine_mode mode;
+     int endp;
 {
   if (!validate_arglist (arglist,
                         POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
@@ -2316,7 +2321,15 @@ expand_builtin_memcpy (arglist, target, mode)
          if (GET_MODE (dest_mem) != ptr_mode)
            dest_mem = convert_memory_address (ptr_mode, dest_mem);
 #endif
-         return dest_mem;
+         if (endp)
+           {
+             rtx result = gen_rtx_PLUS (GET_MODE(dest_mem), dest_mem, len_rtx);
+             if (endp == 2)
+               result = simplify_gen_binary (MINUS, GET_MODE(result), result, const1_rtx);
+             return result;
+           }
+         else
+           return dest_mem;
        }
 
       src_mem = get_memory_rtx (src);
@@ -2335,7 +2348,15 @@ expand_builtin_memcpy (arglist, target, mode)
 #endif
        }
 
-      return dest_addr;
+      if (endp)
+        {
+         rtx result = gen_rtx_PLUS (GET_MODE (dest_addr), dest_addr, len_rtx);
+         if (endp == 2)
+           result = simplify_gen_binary (MINUS, GET_MODE(result), result, const1_rtx);
+         return result;
+       }
+      else
+       return dest_addr;
     }
 }
 
@@ -2370,6 +2391,31 @@ expand_builtin_strcpy (exp, target, mode)
                      target, mode, EXPAND_NORMAL);
 }
 
+/* Expand a call to the stpcpy builtin, with arguments in ARGLIST.
+   Return 0 if we failed the caller should emit a normal call,
+   otherwise try to get the result in TARGET, if convenient (and in
+   mode MODE if that's convenient).  */
+
+static rtx
+expand_builtin_stpcpy (arglist, target, mode)
+     tree arglist;
+     rtx target;
+     enum machine_mode mode;
+{
+  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+    return 0;
+  else
+    {
+      tree len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
+      if (len == 0)
+       return 0;
+
+      len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
+      chainon (arglist, build_tree_list (NULL_TREE, len));
+      return expand_builtin_memcpy (arglist, target, mode, /*endp=*/2);
+    }
+}
+
 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    bytes from constant string DATA + OFFSET and return it as target
    constant.  */
@@ -4036,10 +4082,12 @@ expand_builtin (exp, target, subtarget, mode, ignore)
       case BUILT_IN_MEMSET:
       case BUILT_IN_MEMCPY:
       case BUILT_IN_MEMCMP:
+      case BUILT_IN_MEMPCPY:
       case BUILT_IN_BCMP:
       case BUILT_IN_BZERO:
       case BUILT_IN_INDEX:
       case BUILT_IN_RINDEX:
+      case BUILT_IN_STPCPY:
       case BUILT_IN_STRCHR:
       case BUILT_IN_STRRCHR:
       case BUILT_IN_STRLEN:
@@ -4303,6 +4351,12 @@ expand_builtin (exp, target, subtarget, mode, ignore)
        return target;
       break;
 
+    case BUILT_IN_STPCPY:
+      target = expand_builtin_stpcpy (arglist, target, mode);
+      if (target)
+       return target;
+      break;
+
     case BUILT_IN_STRCAT:
       target = expand_builtin_strcat (arglist, target, mode);
       if (target)
@@ -4354,7 +4408,13 @@ expand_builtin (exp, target, subtarget, mode, ignore)
       break;
 
     case BUILT_IN_MEMCPY:
-      target = expand_builtin_memcpy (arglist, target, mode);
+      target = expand_builtin_memcpy (arglist, target, mode, /*endp=*/0);
+      if (target)
+       return target;
+      break;
+
+    case BUILT_IN_MEMPCPY:
+      target = expand_builtin_memcpy (arglist, target, mode, /*endp=*/1);
       if (target)
        return target;
       break;
index f0df8bb..1d456e9 100644 (file)
@@ -388,6 +388,10 @@ DEF_LIB_BUILTIN(BUILT_IN_MEMSET,
                "__builtin_memset",
                BT_FN_PTR_PTR_INT_SIZE,
                ATTR_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN(BUILT_IN_MEMPCPY,
+               "__builtin_mempcpy",
+               BT_FN_PTR_PTR_CONST_PTR_SIZE,
+               ATTR_NOTHROW_LIST)
 
 DEF_LIB_BUILTIN(BUILT_IN_STRCAT,
                "__builtin_strcat",
@@ -397,6 +401,10 @@ DEF_LIB_BUILTIN(BUILT_IN_STRNCAT,
                "__builtin_strncat",
                BT_FN_STRING_STRING_CONST_STRING_SIZE,
                ATTR_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN(BUILT_IN_STPCPY,
+               "__builtin_stpcpy",
+               BT_FN_STRING_STRING_CONST_STRING,
+               ATTR_NOTHROW_LIST)
 DEF_LIB_BUILTIN(BUILT_IN_STRCPY,
                "__builtin_strcpy",
                BT_FN_STRING_STRING_CONST_STRING,
index ad2a02f..b61a718 100644 (file)
@@ -4598,6 +4598,7 @@ v4si f (v4si a, v4si b, v4si c)
 @findex logl
 @findex memcmp
 @findex memcpy
+@findex mempcpy
 @findex memset
 @findex nearbyint
 @findex nearbyintf
@@ -4623,6 +4624,7 @@ v4si f (v4si a, v4si b, v4si c)
 @findex sqrtf
 @findex sqrtl
 @findex sscanf
+@findex stpcpy
 @findex strcat
 @findex strchr
 @findex strcmp
@@ -4667,8 +4669,8 @@ be emitted.
 Outside strict ISO C mode (@option{-ansi}, @option{-std=c89} or
 @option{-std=c99}), the functions @code{alloca}, @code{bcmp},
 @code{bzero}, @code{_exit}, @code{ffs}, @code{fprintf_unlocked},
-@code{fputs_unlocked}, @code{index}, @code{printf_unlocked},
-and @code{rindex} may be handled as built-in functions.
+@code{fputs_unlocked}, @code{index}, @code{mempcpy}, @code{printf_unlocked},
+@code{rindex}, and @code{stpcpy} may be handled as built-in functions.
 All these functions have corresponding versions
 prefixed with @code{__builtin_}, which may be used even in strict C89
 mode.
index b7366d6..3b8b5c5 100644 (file)
@@ -1,3 +1,7 @@
+2003-04-13  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * gcc.c-torture/execute/string-opt-18.c: New test.
+
 2003-04-13  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/10300
diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c
new file mode 100644 (file)
index 0000000..cc74489
--- /dev/null
@@ -0,0 +1,91 @@
+#include <stdio.h>
+/* Copyright (C) 2000  Free Software Foundation.
+
+   Ensure builtin mempcpy and stpcpy perform correctly.
+
+   Written by Kaveh Ghazi, 4/11/2003.  */
+
+extern void abort (void);
+extern char *strcpy (char *, const char *);
+extern char *stpcpy (char *, const char *);
+/*typedef __SIZE_TYPE__ size_t;*/
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern void *mempcpy (void *, const void *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+
+const char s1[] = "123";
+char p[32] = "";
+
+int main()
+{
+  int i;
+  const char *s;
+
+  if (stpcpy (p, "abcde") != p + 5 || memcmp (p, "abcde", 6))
+    abort ();
+  if (stpcpy (p + 16, "vwxyz" + 1) != p + 16 + 4 || memcmp (p + 16, "wxyz", 5))
+    abort ();
+  if (stpcpy (p + 1, "") != p + 1 + 0 || memcmp (p, "a\0cde", 6))
+    abort ();  
+  if (stpcpy (p + 3, "fghij") != p + 3 + 5 || memcmp (p, "a\0cfghij", 9))
+    abort ();
+  if (mempcpy (p, "ABCDE", 6) != p + 6 || memcmp (p, "ABCDE", 6))
+    abort ();
+  if (mempcpy (p + 16, "VWX" + 1, 2) != p + 16 + 2 || memcmp (p + 16, "WXyz", 5))
+    abort ();
+  if (mempcpy (p + 1, "", 1) != p + 1 + 1 || memcmp (p, "A\0CDE", 6))
+    abort ();  
+  if (mempcpy (p + 3, "FGHI", 4) != p + 3 + 4 || memcmp (p, "A\0CFGHIj", 9))
+    abort ();
+
+  i = 8;
+  memcpy (p + 20, "qrstu", 6);
+  if (stpcpy ((i++, p + 20 + 1), "23") != (p + 20 + 1 + 2) || i != 9 || memcmp (p + 20, "q23\0u", 6))
+    abort ();
+
+  s = s1; i = 3;
+  memcpy (p + 25, "QRSTU", 6);
+  if (mempcpy (p + 25 + 1, s++, i++) != (p + 25 + 1 + 3) || i != 4 || s != s1 + 1 || memcmp (p + 25, "Q123U", 6))
+    abort ();
+
+  if (stpcpy (stpcpy (p, "ABCD"), "EFG") != p + 7 || memcmp (p, "ABCDEFG", 8))
+    abort();
+  if (mempcpy (mempcpy (p, "abcdEFG", 4), "efg", 4) != p + 8 || memcmp (p, "abcdefg", 8))
+    abort();
+  
+  /* Test at least one instance of the __builtin_ style.  We do this
+     to ensure that it works and that the prototype is correct.  */
+  if (__builtin_stpcpy (p, "abcde") != p + 5 || memcmp (p, "abcde", 6))
+    abort ();
+  if (__builtin_mempcpy (p, "ABCDE", 6) != p + 6 || memcmp (p, "ABCDE", 6))
+    abort ();
+
+  return 0;
+}
+
+/* When optimizing, all the above cases should be transformed into
+   something else.  So any remaining calls to the original function
+   should abort.  When not optimizing, we provide fallback funcs for
+   platforms that don't have mempcpy or stpcpy in libc.*/
+__attribute__ ((noinline))
+static char *
+stpcpy (char *d, const char *s)
+{
+#ifdef __OPTIMIZE__
+  abort ();
+#else
+  return strcpy (d, s) + strlen (s);
+#endif
+}
+
+__attribute__ ((noinline))
+static void *
+mempcpy (void *dst, const void *src, size_t sz)
+{
+#ifdef __OPTIMIZE__
+  abort ();
+#else
+  return (char *) memcpy (dst, src, sz) + sz;
+#endif
+}