This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch to add builtin mempcpy and stpcpy


This patch adds two new builtins, mempcpy and stpcpy.  These builtin
functions are added as the "extension" type, like alloca, bzero, etc.

The transformations for these two are the same as those for memcpy and
strcpy except the return values for these are different as commonly
defined in glibc et al.

Bootstrapped on sparc-sun-solaris2.7, no regressions.  And the new
testcase passes.

Ok for mainline?

		Thanks,
		--Kaveh


2003-04-11  Kaveh R. Ghazi  <ghazi at caip dot rutgers dot edu>

gcc:
	* 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 builtin.
	
testsuite:
	* gcc.c-torture/execute/string-opt-18.c: New test.

diff -rup orig/egcc-CVS20030410/gcc/builtins.c egcc-CVS20030410/gcc/builtins.c
--- orig/egcc-CVS20030410/gcc/builtins.c	2003-04-08 21:01:05.000000000 -0400
+++ egcc-CVS20030410/gcc/builtins.c	2003-04-11 17:34:41.285255000 -0400
@@ -125,9 +125,11 @@ static rtx expand_builtin_strspn	PARAMS 
 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, m
 }
 
 /* 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, 
 	  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, 
 #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.  */
@@ -4055,10 +4101,12 @@ expand_builtin (exp, target, subtarget, 
       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:
@@ -4322,6 +4370,12 @@ expand_builtin (exp, target, subtarget, 
 	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)
@@ -4373,7 +4427,13 @@ expand_builtin (exp, target, subtarget, 
       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;
diff -rup orig/egcc-CVS20030410/gcc/builtins.def egcc-CVS20030410/gcc/builtins.def
--- orig/egcc-CVS20030410/gcc/builtins.def	2003-03-09 21:27:05.000000000 -0500
+++ egcc-CVS20030410/gcc/builtins.def	2003-04-11 14:54:17.249427000 -0400
@@ -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,
diff -rup orig/egcc-CVS20030410/gcc/doc/extend.texi egcc-CVS20030410/gcc/doc/extend.texi
--- orig/egcc-CVS20030410/gcc/doc/extend.texi	2003-04-07 21:01:44.000000000 -0400
+++ egcc-CVS20030410/gcc/doc/extend.texi	2003-04-11 14:54:59.036035000 -0400
@@ -4582,6 +4582,7 @@ v4si f (v4si a, v4si b, v4si c)
 @findex logl
 @findex memcmp
 @findex memcpy
+ at findex mempcpy
 @findex memset
 @findex nearbyint
 @findex nearbyintf
@@ -4607,6 +4608,7 @@ v4si f (v4si a, v4si b, v4si c)
 @findex sqrtf
 @findex sqrtl
 @findex sscanf
+ at findex stpcpy
 @findex strcat
 @findex strchr
 @findex strcmp
@@ -4651,8 +4653,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},
- at code{fputs_unlocked}, @code{index}, @code{printf_unlocked},
-and @code{rindex} may be handled as built-in functions.
+ at code{fputs_unlocked}, @code{index}, @code{mempcpy}, @code{printf_unlocked},
+ at 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.
diff -rup orig/egcc-CVS20030410/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c egcc-CVS20030410/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c
--- orig/egcc-CVS20030410/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c	2003-04-11 15:06:39.068170000 -0400
+++ egcc-CVS20030410/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c	2003-04-11 17:48:17.518862000 -0400
@@ -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
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]