Add support for copy specifiers in fnspec
authorJan Hubicka <jh@suse.cz>
Thu, 12 Nov 2020 13:56:40 +0000 (14:56 +0100)
committerJan Hubicka <jh@suse.cz>
Thu, 12 Nov 2020 13:56:40 +0000 (14:56 +0100)
* attr-fnspec.h: Update topleve comment.
(attr_fnspec::arg_direct_p): Accept 1...9.
(attr_fnspec::arg_maybe_written_p): Reject 1...9.
(attr_fnspec::arg_copied_to_arg_p): New member function.
* builtins.c (builtin_fnspec): Update fnspec of block copy.
* tree-ssa-alias.c (attr_fnspec::verify): Update.

gcc/attr-fnspec.h
gcc/builtins.c
gcc/tree-ssa-alias.c

index 2813532..b4b49e9 100644 (file)
@@ -41,6 +41,9 @@
                written and does not escape
      'w' or 'W' specifies that the memory pointed to by the parameter does not
                escape
+     '1'....'9' specifies that the memory pointed to by the parameter is
+               copied to memory pointed to by different parameter
+               (as in memcpy).
      '.'       specifies that nothing is known.
    The uppercase letter in addition specifies that the memory pointed to
    by the parameter is not dereferenced.  For 'r' only read applies
@@ -51,8 +54,8 @@
      ' '        nothing is known
      't'       the size of value written/read corresponds to the size of
                of the pointed-to type of the argument type
-     '1'...'9'  the size of value written/read is given by the specified
-               argument
+     '1'...'9'  specifies the size of value written/read is given by the
+               specified argument
  */
 
 #ifndef ATTR_FNSPEC_H
@@ -122,7 +125,8 @@ public:
   {
     unsigned int idx = arg_idx (i);
     gcc_checking_assert (arg_specified_p (i));
-    return str[idx] == 'R' || str[idx] == 'O' || str[idx] == 'W';
+    return str[idx] == 'R' || str[idx] == 'O'
+          || str[idx] == 'W' || (str[idx] >= '1' && str[idx] <= '9');
   }
 
   /* True if argument is used.  */
@@ -161,6 +165,7 @@ public:
     unsigned int idx = arg_idx (i);
     gcc_checking_assert (arg_specified_p (i));
     return str[idx] != 'r' && str[idx] != 'R'
+          && (str[idx] < '1' || str[idx] > '9')
           && str[idx] != 'x' && str[idx] != 'X';
   }
 
@@ -190,6 +195,21 @@ public:
     return str[idx + 1] == 't';
   }
 
+  /* Return true if memory pointer to by argument is copied to a memory
+     pointed to by a different argument (as in memcpy).
+     In this case set ARG.  */
+  bool
+  arg_copied_to_arg_p (unsigned int i, unsigned int *arg)
+  {
+    unsigned int idx = arg_idx (i);
+    gcc_checking_assert (arg_specified_p (i));
+    if (str[idx] < '1' || str[idx] > '9')
+      return false;
+    *arg = str[idx] - '1';
+    return true;
+  }
+
+
   /* True if the argument does not escape.  */
   bool
   arg_noescape_p (unsigned int i)
@@ -230,7 +250,7 @@ public:
     return str[1] != 'c' && str[1] != 'C';
   }
 
-  /* Return true if all memory written by the function 
+  /* Return true if all memory written by the function
      is specified by fnspec.  */
   bool
   global_memory_written_p ()
index da25343..4ec1766 100644 (file)
@@ -12939,16 +12939,16 @@ builtin_fnspec (tree callee)
         argument.  */
       case BUILT_IN_STRCAT:
       case BUILT_IN_STRCAT_CHK:
-       return "1cW R ";
+       return "1cW 1 ";
       case BUILT_IN_STRNCAT:
       case BUILT_IN_STRNCAT_CHK:
-       return "1cW R3";
+       return "1cW 13";
       case BUILT_IN_STRCPY:
       case BUILT_IN_STRCPY_CHK:
-       return "1cO R ";
+       return "1cO 1 ";
       case BUILT_IN_STPCPY:
       case BUILT_IN_STPCPY_CHK:
-       return ".cO R ";
+       return ".cO 1 ";
       case BUILT_IN_STRNCPY:
       case BUILT_IN_MEMCPY:
       case BUILT_IN_MEMMOVE:
@@ -12957,15 +12957,15 @@ builtin_fnspec (tree callee)
       case BUILT_IN_STRNCPY_CHK:
       case BUILT_IN_MEMCPY_CHK:
       case BUILT_IN_MEMMOVE_CHK:
-       return "1cO3R3";
+       return "1cO313";
       case BUILT_IN_MEMPCPY:
       case BUILT_IN_MEMPCPY_CHK:
-       return ".cO3R3";
+       return ".cO313";
       case BUILT_IN_STPNCPY:
       case BUILT_IN_STPNCPY_CHK:
-       return ".cO3R3";
+       return ".cO313";
       case BUILT_IN_BCOPY:
-       return ".cR3O3";
+       return ".c23O3";
       case BUILT_IN_BZERO:
        return ".cO2";
       case BUILT_IN_MEMCMP:
index e64011d..b1e8e5b 100644 (file)
@@ -3797,6 +3797,8 @@ attr_fnspec::verify ()
       default:
        err = true;
     }
+  if (err)
+    internal_error ("invalid fn spec attribute \"%s\"", str);
 
   /* Now check all parameters.  */
   for (unsigned int i = 0; arg_specified_p (i); i++)
@@ -3813,21 +3815,28 @@ attr_fnspec::verify ()
          case 'w':
          case 'W':
          case '.':
+           if ((str[idx + 1] >= '1' && str[idx + 1] <= '9')
+               || str[idx + 1] == 't')
+             {
+               if (str[idx] != 'r' && str[idx] != 'R'
+                   && str[idx] != 'w' && str[idx] != 'W'
+                   && str[idx] != 'o' && str[idx] != 'O')
+                 err = true;
+               if (str[idx] != 't'
+                   /* Size specified is scalar, so it should be described
+                      by ". " if specified at all.  */
+                   && (arg_specified_p (str[idx + 1] - '1')
+                       && str[arg_idx (str[idx + 1] - '1')] != '.'))
+                 err = true;
+             }
+           else if (str[idx + 1] != ' ')
+             err = true;
            break;
          default:
-           err = true;
+           if (str[idx] < '1' || str[idx] > '9')
+             err = true;
        }
-      if ((str[idx + 1] >= '1' && str[idx + 1] <= '9')
-         || str[idx + 1] == 't')
-       {
-         if (str[idx] != 'r' && str[idx] != 'R'
-             && str[idx] != 'w' && str[idx] != 'W'
-             && str[idx] != 'o' && str[idx] != 'O')
-           err = true;
-       }
-      else if (str[idx + 1] != ' ')
-       err = true;
+      if (err)
+       internal_error ("invalid fn spec attribute \"%s\" arg %i", str, i);
     }
-  if (err)
-    internal_error ("invalid fn spec attribute \"%s\"", str);
 }