From 071a31a53388229213f323ecdc680ff8aeda456c Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Thu, 12 Nov 2020 14:56:40 +0100 Subject: [PATCH] Add support for copy specifiers in fnspec * 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 | 28 ++++++++++++++++++++++++---- gcc/builtins.c | 16 ++++++++-------- gcc/tree-ssa-alias.c | 35 ++++++++++++++++++++++------------- 3 files changed, 54 insertions(+), 25 deletions(-) diff --git a/gcc/attr-fnspec.h b/gcc/attr-fnspec.h index 28135328437..b4b49e93fc4 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 da25343beb1..4ec1766cffd 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 e64011d04df..b1e8e5b5352 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); } -- 2.30.2