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]

Patch to create builtin strncmp


	This patch creates a new builtin strncmp.  It operates
similarly to the strcmp builtin except that it also clamps on the
third arg (which must be a constant.)  This patch depends on
http://gcc.gnu.org/ml/gcc-patches/2000-03/msg00745.html

Bootstrapped on i686-pc-linux-gnu and sparc-sun-solaris2.7, no regressions.
Okay to install?

		--Kaveh



2000-03-21  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

	* builtins.c (expand_builtin_strncmp): New function.
	(expand_builtin): Handle strncmp.

	* builtins.def: Add BUILT_IN_STRNCMP.

	* c-common.c (c_common_nodes_and_builtins): Provide builtin
	prototype & function for strncmp.

diff -rup orig/egcs-CVS20000321/gcc/builtins.c egcs-CVS20000321/gcc/builtins.c
--- orig/egcs-CVS20000321/gcc/builtins.c	Tue Mar 21 21:51:05 2000
+++ egcs-CVS20000321/gcc/builtins.c	Tue Mar 21 22:10:54 2000
@@ -92,6 +92,7 @@ static rtx expand_builtin_va_copy	PARAMS
 #ifdef HAVE_cmpstrsi
 static rtx expand_builtin_memcmp	PARAMS ((tree, tree, rtx));
 static rtx expand_builtin_strcmp	PARAMS ((tree, rtx));
+static rtx expand_builtin_strncmp	PARAMS ((tree, rtx));
 #endif
 static rtx expand_builtin_memcpy	PARAMS ((tree));
 static rtx expand_builtin_strcpy	PARAMS ((tree));
@@ -1712,6 +1713,88 @@ expand_builtin_strcmp (exp, target)
     return result;
   }
 }
+
+/* Expand expression EXP, which is a call to the strncmp builtin.  Return 0
+   if we failed the caller should emit a normal call, otherwise try to get
+   the result in TARGET, if convenient.  */
+static rtx
+expand_builtin_strncmp (exp, target)
+     tree exp;
+     rtx target;
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+
+  /* If we need to check memory accesses, call the library function.  */
+  if (current_function_check_memory_usage)
+    return 0;
+
+  if (arglist == 0
+      /* Arg could be non-pointer if user redeclared this fcn wrong.  */
+      || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
+      || TREE_CHAIN (arglist) == 0
+      || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
+      || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
+      || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
+    return 0;
+  else if (!HAVE_cmpstrsi)
+    return 0;
+  {
+    tree arg1 = TREE_VALUE (arglist);
+    tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
+    tree arg3 = TREE_CHAIN (TREE_CHAIN (arglist));
+    tree len, len2;
+    rtx result;
+    len = c_strlen (arg1);
+    if (len)
+      len = size_binop (PLUS_EXPR, ssize_int(1), len);
+    len2 = c_strlen (arg2);
+    if (len2)
+      len2 = size_binop (PLUS_EXPR, ssize_int(1), len2);
+
+    /* If we don't have a constant length for the first, use the length
+       of the second, if we know it.  We don't require a constant for
+       this case; some cost analysis could be done if both are available
+       but neither is constant.  For now, assume they're equally cheap.
+
+       If both strings have constant lengths, use the smaller.  This
+       could arise if optimization results in strcpy being called with
+       two fixed strings, or if the code was machine-generated.  We should
+       add some code to the `memcmp' handler below to deal with such
+       situations, someday.  */
+    if (!len || TREE_CODE (len) != INTEGER_CST)
+      {
+	if (len2)
+	  len = len2;
+	else if (len == 0)
+	  return 0;
+      }
+    else if (len2 && TREE_CODE (len2) == INTEGER_CST)
+      {
+	if (tree_int_cst_lt (len2, len))
+	  len = len2;
+      }
+
+    /* If the max length to check is not constant, punt.  */
+    if (!arg3 || TREE_CODE (TREE_VALUE (arg3)) != INTEGER_CST)
+      return 0;
+    
+    /* If arg3 is less than either string length, clamp at arg3.  */
+    if (tree_int_cst_lt (TREE_VALUE (arg3), len))
+      len = arg3;
+    else
+      len = build_tree_list (NULL_TREE, len);
+    
+    TREE_CHAIN (TREE_CHAIN (arglist)) = len;
+    TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))) = 0;
+
+    result = expand_builtin_memcmp (exp, arglist, target);
+
+    /* Restore original arg3 if builtin memcmp failed.  */
+    if (! result)
+      TREE_CHAIN (TREE_CHAIN (arglist)) = arg3;
+    return result;
+  }
+}
 #endif
 
 /* Expand a call to __builtin_saveregs, generating the result in TARGET,
@@ -2314,7 +2397,8 @@ expand_builtin (exp, target, subtarget, 
 	  || fcode == BUILT_IN_FSQRT || fcode == BUILT_IN_MEMSET
 	  || fcode == BUILT_IN_MEMCPY || fcode == BUILT_IN_MEMCMP
 	  || fcode == BUILT_IN_STRLEN || fcode == BUILT_IN_STRCPY
-	  || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS))
+	  || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_STRNCMP
+	  || fcode == BUILT_IN_FFS))
     return expand_call (exp, target, ignore);
 
   switch (fcode)
@@ -2460,6 +2544,12 @@ expand_builtin (exp, target, subtarget, 
 	return target;
       break;
 
+    case BUILT_IN_STRNCMP:
+      target = expand_builtin_strncmp (exp, target);
+      if (target)
+	return target;
+      break;
+      
     case BUILT_IN_MEMCMP:
       target = expand_builtin_memcmp (exp, arglist, target);
       if (target)
@@ -2467,6 +2557,7 @@ expand_builtin (exp, target, subtarget, 
       break;
 #else
     case BUILT_IN_STRCMP:
+    case BUILT_IN_STRNCMP:
     case BUILT_IN_MEMCMP:
       break;
 #endif
diff -rup orig/egcs-CVS20000321/gcc/builtins.def egcs-CVS20000321/gcc/builtins.def
--- orig/egcs-CVS20000321/gcc/builtins.def	Tue Mar 21 21:51:05 2000
+++ egcs-CVS20000321/gcc/builtins.def	Tue Mar 21 21:52:04 2000
@@ -35,6 +35,7 @@ DEF_BUILTIN(BUILT_IN_MEMCMP)
 DEF_BUILTIN(BUILT_IN_MEMSET)
 DEF_BUILTIN(BUILT_IN_STRCPY)
 DEF_BUILTIN(BUILT_IN_STRCMP)
+DEF_BUILTIN(BUILT_IN_STRNCMP)
 DEF_BUILTIN(BUILT_IN_STRLEN)
 DEF_BUILTIN(BUILT_IN_FSQRT)
 DEF_BUILTIN(BUILT_IN_SIN)
diff -rup orig/egcs-CVS20000321/gcc/c-common.c egcs-CVS20000321/gcc/c-common.c
--- orig/egcs-CVS20000321/gcc/c-common.c	Tue Mar 21 16:21:35 2000
+++ egcs-CVS20000321/gcc/c-common.c	Tue Mar 21 22:00:31 2000
@@ -3464,6 +3464,7 @@ c_common_nodes_and_builtins (cplus_mode,
 {
   tree temp;
   tree memcpy_ftype, memset_ftype, strlen_ftype;
+  tree strncmp_ftype;
   tree endlink, int_endlink, double_endlink, unsigned_endlink;
   tree sizetype_endlink;
   tree ptr_ftype, ptr_ftype_unsigned;
@@ -3475,6 +3476,8 @@ c_common_nodes_and_builtins (cplus_mode,
   tree long_ftype_long;
   /* Either char* or void*.  */
   tree traditional_ptr_type_node;
+  tree traditional_len_type_node;
+  tree traditional_len_endlink;
   tree va_list_ptr_type_node;
   tree va_list_arg_type_node;
 
@@ -3561,10 +3564,22 @@ c_common_nodes_and_builtins (cplus_mode,
 						 const_string_type_node,
 						 endlink)));
 
+  traditional_len_type_node = (flag_traditional && ! cplus_mode
+			       ? integer_type_node : sizetype);
+  traditional_len_endlink = tree_cons (NULL_TREE, traditional_len_type_node,
+				       endlink);
+
+  /* Prototype for strncmp.  */
+  strncmp_ftype
+    = build_function_type (integer_type_node,
+			   tree_cons (NULL_TREE, const_string_type_node,
+				      tree_cons (NULL_TREE,
+						 const_string_type_node,
+						 traditional_len_endlink)));
+
   /* Prototype for strlen.  */
   strlen_ftype
-    = build_function_type ((flag_traditional && ! cplus_mode
-			    ? integer_type_node : sizetype),
+    = build_function_type (traditional_len_type_node,
 			   tree_cons (NULL_TREE, const_string_type_node,
 				      endlink));
 
@@ -3727,6 +3742,8 @@ c_common_nodes_and_builtins (cplus_mode,
 		    BUILT_IN_NORMAL, "memset");
   builtin_function ("__builtin_strcmp", int_ftype_string_string,
 		    BUILT_IN_STRCMP, BUILT_IN_NORMAL, "strcmp");
+  builtin_function ("__builtin_strncmp", strncmp_ftype,
+		    BUILT_IN_STRNCMP, BUILT_IN_NORMAL, "strncmp");
   builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr,
 		    BUILT_IN_STRCPY, BUILT_IN_NORMAL, "strcpy");
   builtin_function ("__builtin_strlen", strlen_ftype,
@@ -3769,6 +3786,8 @@ c_common_nodes_and_builtins (cplus_mode,
       builtin_function ("memset", memset_ftype, BUILT_IN_MEMSET,
 			BUILT_IN_NORMAL, NULL_PTR);
       builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP,
+			BUILT_IN_NORMAL, NULL_PTR);
+      builtin_function ("strncmp", strncmp_ftype, BUILT_IN_STRNCMP,
 			BUILT_IN_NORMAL, NULL_PTR);
       builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY,
 			BUILT_IN_NORMAL, NULL_PTR);

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