aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/attr-fnspec.h28
-rw-r--r--gcc/builtins.c16
-rw-r--r--gcc/tree-ssa-alias.c35
3 files changed, 54 insertions, 25 deletions
diff --git a/gcc/attr-fnspec.h b/gcc/attr-fnspec.h
index 28135328..b4b49e9 100644
--- a/gcc/attr-fnspec.h
+++ b/gcc/attr-fnspec.h
@@ -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 ()
diff --git a/gcc/builtins.c b/gcc/builtins.c
index da25343..4ec1766 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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:
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index e64011d..b1e8e5b 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -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);
}