diff options
author | Jakub Jelinek <jakub@redhat.com> | 2005-06-27 14:17:39 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2005-06-27 14:17:39 +0200 |
commit | 10a0d4957162e39a922341ffbef5a394035cf17c (patch) | |
tree | bb3939873bf2cf5cb7bd56f678141658affb0021 /gcc/tree-ssa-ccp.c | |
parent | de16a5b6a405055fe49ac876878ebe2a65459b42 (diff) | |
download | gcc-10a0d4957162e39a922341ffbef5a394035cf17c.zip gcc-10a0d4957162e39a922341ffbef5a394035cf17c.tar.gz gcc-10a0d4957162e39a922341ffbef5a394035cf17c.tar.bz2 |
builtin-attrs.def (DEF_ATTR_FOR_INT): Add for 5 and 6.
* builtin-attrs.def (DEF_ATTR_FOR_INT): Add for 5 and 6.
(DEF_LIST_INT_INT): Add for 4,0, 4,5, 5,0, 5,6.
(ATTR_NOTHROW_NONNULL_4, ATTR_NOTHROW_NONNULL_5): Define.
(ATTR_FORMAT_PRINTF_4_0, ATTR_FORMAT_PRINTF_4_5,
ATTR_FORMAT_PRINTF_5_0, ATTR_FORMAT_PRINTF_5_6): Define.
* builtins.c: Include tree-flow.h.
(expand_builtin_mempcpy, expand_builtin_memmove): Comment fixes.
(expand_builtin_object_size, expand_builtin_memory_chk,
maybe_emit_chk_warning, maybe_emit_sprintf_chk_warning,
compute_object_offset, compute_builtin_object_size,
fold_builtin_object_size): New functions.
(expand_builtin): Handle BUILT_IN_OBJECT_SIZE and BUILT_IN_*_CHK.
(fold_builtin_1): Likewise. Handle BUILT_IN_{,V}{,F}PRINTF
and BUILT_IN_{,F}PRINTF_UNLOCKED.
(fold_builtin_memory_chk, fold_builtin_stxcpy_chk,
fold_builtin_strncpy_chk, fold_builtin_strcat_chk,
fold_builtin_strncat_chk, fold_builtin_sprintf_chk,
fold_builtin_snprintf_chk, fold_builtin_printf, fold_builtin_fprintf):
New functions.
* builtins.def (BUILT_IN_OBJECT_SIZE, BUILT_IN_MEMCPY_CHK,
BUILT_IN_MEMMOVE_CHK, BUILT_IN_MEMPCPY_CHK, BUILT_IN_MEMSET_CHK,
BUILT_IN_STPCPY_CHK, BUILT_IN_STRCAT_CHK, BUILT_IN_STRCPY_CHK,
BUILT_IN_STRNCAT_CHK, BUILT_IN_STRNCPY_CHK, BUILT_IN_SNPRINTF_CHK,
BUILT_IN_SPRINTF_CHK, BUILT_IN_VSNPRINTF_CHK, BUILT_IN_VSPRINTF_CHK,
BUILT_IN_FPRINTF_CHK, BUILT_IN_PRINTF_CHK, BUILT_IN_VFPRINTF_CHK,
BUILT_IN_VPRINTF_CHK): New builtins.
* builtin-types.def (DEF_FUNCTION_TYPE_5, DEF_FUNCTION_TYPE_VAR_4):
Document.
(BT_FN_SIZE_CONST_PTR_INT, BT_FN_INT_INT_CONST_STRING_VALIST_ARG,
BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, BT_FN_PTR_PTR_INT_SIZE_SIZE,
BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE,
BT_FN_INT_FILEPTR_INT_CONST_STRING_VALIST_ARG,
BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG,
BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VALIST_ARG,
BT_FN_INT_INT_CONST_STRING_VAR, BT_FN_INT_FILEPTR_INT_CONST_STRING_VAR,
BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VAR,
BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VAR): New types.
* c-common.c (DEF_FUNCTION_TYPE_5, DEF_FUNCTION_TYPE_6,
DEF_FUNCTION_TYPE_VAR_4, DEF_FUNCTION_TYPE_VAR_5): Define.
* Makefile.in (OBJS-common): Add tree-object-size.o.
(tree-object-size.o): Add dependencies.
* tree-pass.h (pass_object_sizes): Add.
* tree-optimize.c (init_tree_optimization_passes): Add
pass_object_sizes.
* tree-object-size.c: New file.
* tree.h (fold_builtin_memory_chk, fold_builtin_stxcpy_chk,
fold_builtin_strncpy_chk, fold_builtin_snprintf_chk,
compute_builtin_object_size, init_object_sizes, fini_object_sizes):
New prototypes.
* tree-ssa-ccp.c (get_strlen): Rename to ...
(get_maxval_strlen): ...this function. Handle also computing of maximum
string length and maximum integral value.
(ccp_fold_builtin): Handle BUILT_IN_*_CHK. Use get_maxval_strlen
instead of get_strlen. Pass CALLEE and ARGLIST variables to the
folding functions instead of computing them again.
(execute_fold_all_builtins): Retry ccp_fold_builtin if a builtin changed
into some other builtin.
* doc/extend.texi (Object Size Checking): Document.
* gcc.c-torture/execute/builtins/lib/main.c (abort): Add prototype.
* gcc.c-torture/execute/builtins/lib/strncat.c (strncat): Avoid
testing uninitialized var.
* gcc.c-torture/execute/builtins/chk.h: New.
* gcc.c-torture/execute/builtins/lib/chk.c: New.
* gcc.c-torture/execute/builtins/memcpy-chk.c: New test.
* gcc.c-torture/execute/builtins/memcpy-chk-lib.c: New.
* gcc.c-torture/execute/builtins/memmove-chk.c: New test.
* gcc.c-torture/execute/builtins/memmove-chk-lib.c: New.
* gcc.c-torture/execute/builtins/mempcpy-chk.c: New test.
* gcc.c-torture/execute/builtins/mempcpy-chk-lib.c: New.
* gcc.c-torture/execute/builtins/memset-chk.c: New test.
* gcc.c-torture/execute/builtins/memset-chk-lib.c: New.
* gcc.c-torture/execute/builtins/snprintf-chk.c: New test.
* gcc.c-torture/execute/builtins/snprintf-chk-lib.c: New.
* gcc.c-torture/execute/builtins/sprintf-chk.c: New test.
* gcc.c-torture/execute/builtins/sprintf-chk-lib.c: New.
* gcc.c-torture/execute/builtins/stpcpy-chk.c: New test.
* gcc.c-torture/execute/builtins/stpcpy-chk-lib.c: New.
* gcc.c-torture/execute/builtins/strcat-chk.c: New test.
* gcc.c-torture/execute/builtins/strcat-chk-lib.c: New.
* gcc.c-torture/execute/builtins/strcpy-chk.c: New test.
* gcc.c-torture/execute/builtins/strcpy-chk-lib.c: New.
* gcc.c-torture/execute/builtins/strncat-chk.c: New test.
* gcc.c-torture/execute/builtins/strncat-chk-lib.c: New.
* gcc.c-torture/execute/builtins/strncpy-chk.c: New test.
* gcc.c-torture/execute/builtins/strncpy-chk-lib.c: New.
* gcc.c-torture/execute/builtins/vsnprintf-chk.c: New test.
* gcc.c-torture/execute/builtins/vsnprintf-chk-lib.c: New.
* gcc.c-torture/execute/builtins/vsprintf-chk.c: New test.
* gcc.c-torture/execute/builtins/vsprintf-chk-lib.c: New.
* gcc.dg/builtin-object-size-1.c: New test.
* gcc.dg/builtin-object-size-2.c: New test.
* gcc.dg/builtin-object-size-3.c: New test.
* gcc.dg/builtin-object-size-4.c: New test.
* gcc.dg/builtin-object-size-5.c: New test.
* gcc.dg/builtin-stringop-chk-1.c: New test.
* gcc.dg/builtin-stringop-chk-2.c: New test.
* gcc.dg/tree-ssa/builtin-fprintf-1.c: New test.
* gcc.dg/tree-ssa/builtin-fprintf-chk-1.c: New test.
* gcc.dg/tree-ssa/builtin-printf-1.c: New test.
* gcc.dg/tree-ssa/builtin-printf-chk-1.c: New test.
* gcc.dg/tree-ssa/builtin-vfprintf-1.c: New test.
* gcc.dg/tree-ssa/builtin-vfprintf-chk-1.c: New test.
* gcc.dg/tree-ssa/builtin-vprintf-1.c: New test.
* gcc.dg/tree-ssa/builtin-vprintf-chk-1.c: New test.
* gcc.c-torture/execute/printf-1.c: New test.
* gcc.c-torture/execute/fprintf-1.c: New test.
* gcc.c-torture/execute/vprintf-1.c: New test.
* gcc.c-torture/execute/vfprintf-1.c: New test.
* gcc.c-torture/execute/printf-chk-1.c: New test.
* gcc.c-torture/execute/fprintf-chk-1.c: New test.
* gcc.c-torture/execute/vprintf-chk-1.c: New test.
* gcc.c-torture/execute/vfprintf-chk-1.c: New test.
From-SVN: r101352
Diffstat (limited to 'gcc/tree-ssa-ccp.c')
-rw-r--r-- | gcc/tree-ssa-ccp.c | 194 |
1 files changed, 134 insertions, 60 deletions
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 71385dd..8bf8242 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -1965,24 +1965,49 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data) } -/* Return the string length of ARG in LENGTH. If ARG is an SSA name variable, - follow its use-def chains. If LENGTH is not NULL and its value is not - equal to the length we determine, or if we are unable to determine the - length, return false. VISITED is a bitmap of visited variables. */ +/* Return the string length, maximum string length or maximum value of + ARG in LENGTH. + If ARG is an SSA name variable, follow its use-def chains. If LENGTH + is not NULL and, for TYPE == 0, its value is not equal to the length + we determine or if we are unable to determine the length or value, + return false. VISITED is a bitmap of visited variables. + TYPE is 0 if string length should be returned, 1 for maximum string + length and 2 for maximum value ARG can have. */ static bool -get_strlen (tree arg, tree *length, bitmap visited) +get_maxval_strlen (tree arg, tree *length, bitmap visited, int type) { tree var, def_stmt, val; if (TREE_CODE (arg) != SSA_NAME) { - val = c_strlen (arg, 1); + if (type == 2) + { + val = arg; + if (TREE_CODE (val) != INTEGER_CST + || tree_int_cst_sgn (val) < 0) + return false; + } + else + val = c_strlen (arg, 1); if (!val) return false; - if (*length && simple_cst_equal (val, *length) != 1) - return false; + if (*length) + { + if (type > 0) + { + if (TREE_CODE (*length) != INTEGER_CST + || TREE_CODE (val) != INTEGER_CST) + return false; + + if (tree_int_cst_lt (*length, val)) + *length = val; + return true; + } + else if (simple_cst_equal (val, *length) != 1) + return false; + } *length = val; return true; @@ -2000,28 +2025,14 @@ get_strlen (tree arg, tree *length, bitmap visited) { case MODIFY_EXPR: { - tree len, rhs; - + tree rhs; + /* The RHS of the statement defining VAR must either have a constant length or come from another SSA_NAME with a constant length. */ rhs = TREE_OPERAND (def_stmt, 1); STRIP_NOPS (rhs); - if (TREE_CODE (rhs) == SSA_NAME) - return get_strlen (rhs, length, visited); - - /* See if the RHS is a constant length. */ - len = c_strlen (rhs, 1); - if (len) - { - if (*length && simple_cst_equal (len, *length) != 1) - return false; - - *length = len; - return true; - } - - break; + return get_maxval_strlen (rhs, length, visited, type); } case PHI_NODE: @@ -2043,7 +2054,7 @@ get_strlen (tree arg, tree *length, bitmap visited) if (arg == PHI_RESULT (def_stmt)) continue; - if (!get_strlen (arg, length, visited)) + if (!get_maxval_strlen (arg, length, visited, type)) return false; } @@ -2065,9 +2076,9 @@ get_strlen (tree arg, tree *length, bitmap visited) static tree ccp_fold_builtin (tree stmt, tree fn) { - tree result, strlen_val[2]; + tree result, val[3]; tree callee, arglist, a; - int strlen_arg, i; + int arg_mask, i, type; bitmap visited; bool ignore; @@ -2079,11 +2090,11 @@ ccp_fold_builtin (tree stmt, tree fn) arglist = TREE_OPERAND (fn, 1); result = fold_builtin (callee, arglist, ignore); if (result) - { - if (ignore) - STRIP_NOPS (result); - return result; - } + { + if (ignore) + STRIP_NOPS (result); + return result; + } /* Ignore MD builtins. */ if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD) @@ -2100,11 +2111,31 @@ ccp_fold_builtin (tree stmt, tree fn) case BUILT_IN_STRLEN: case BUILT_IN_FPUTS: case BUILT_IN_FPUTS_UNLOCKED: - strlen_arg = 1; + arg_mask = 1; + type = 0; break; case BUILT_IN_STRCPY: case BUILT_IN_STRNCPY: - strlen_arg = 2; + arg_mask = 2; + type = 0; + break; + case BUILT_IN_MEMCPY_CHK: + case BUILT_IN_MEMPCPY_CHK: + case BUILT_IN_MEMMOVE_CHK: + case BUILT_IN_MEMSET_CHK: + case BUILT_IN_STRNCPY_CHK: + arg_mask = 4; + type = 2; + break; + case BUILT_IN_STRCPY_CHK: + case BUILT_IN_STPCPY_CHK: + arg_mask = 2; + type = 1; + break; + case BUILT_IN_SNPRINTF_CHK: + case BUILT_IN_VSNPRINTF_CHK: + arg_mask = 2; + type = 2; break; default: return NULL_TREE; @@ -2113,15 +2144,15 @@ ccp_fold_builtin (tree stmt, tree fn) /* Try to use the dataflow information gathered by the CCP process. */ visited = BITMAP_ALLOC (NULL); - memset (strlen_val, 0, sizeof (strlen_val)); + memset (val, 0, sizeof (val)); for (i = 0, a = arglist; - strlen_arg; - i++, strlen_arg >>= 1, a = TREE_CHAIN (a)) - if (strlen_arg & 1) + arg_mask; + i++, arg_mask >>= 1, a = TREE_CHAIN (a)) + if (arg_mask & 1) { bitmap_clear (visited); - if (!get_strlen (TREE_VALUE (a), &strlen_val[i], visited)) - strlen_val[i] = NULL_TREE; + if (!get_maxval_strlen (TREE_VALUE (a), &val[i], visited, type)) + val[i] = NULL_TREE; } BITMAP_FREE (visited); @@ -2130,9 +2161,9 @@ ccp_fold_builtin (tree stmt, tree fn) switch (DECL_FUNCTION_CODE (callee)) { case BUILT_IN_STRLEN: - if (strlen_val[0]) + if (val[0]) { - tree new = fold_convert (TREE_TYPE (fn), strlen_val[0]); + tree new = fold_convert (TREE_TYPE (fn), val[0]); /* If the result is not a valid gimple value, or not a cast of a valid gimple value, then we can not use the result. */ @@ -2144,33 +2175,53 @@ ccp_fold_builtin (tree stmt, tree fn) break; case BUILT_IN_STRCPY: - if (strlen_val[1] && is_gimple_val (strlen_val[1])) - { - tree fndecl = get_callee_fndecl (fn); - tree arglist = TREE_OPERAND (fn, 1); - result = fold_builtin_strcpy (fndecl, arglist, strlen_val[1]); - } + if (val[1] && is_gimple_val (val[1])) + result = fold_builtin_strcpy (callee, arglist, val[1]); break; case BUILT_IN_STRNCPY: - if (strlen_val[1] && is_gimple_val (strlen_val[1])) - { - tree fndecl = get_callee_fndecl (fn); - tree arglist = TREE_OPERAND (fn, 1); - result = fold_builtin_strncpy (fndecl, arglist, strlen_val[1]); - } + if (val[1] && is_gimple_val (val[1])) + result = fold_builtin_strncpy (callee, arglist, val[1]); break; case BUILT_IN_FPUTS: result = fold_builtin_fputs (arglist, TREE_CODE (stmt) != MODIFY_EXPR, 0, - strlen_val[0]); + val[0]); break; case BUILT_IN_FPUTS_UNLOCKED: result = fold_builtin_fputs (arglist, TREE_CODE (stmt) != MODIFY_EXPR, 1, - strlen_val[0]); + val[0]); + break; + + case BUILT_IN_MEMCPY_CHK: + case BUILT_IN_MEMPCPY_CHK: + case BUILT_IN_MEMMOVE_CHK: + case BUILT_IN_MEMSET_CHK: + if (val[2] && is_gimple_val (val[2])) + result = fold_builtin_memory_chk (callee, arglist, val[2], ignore, + DECL_FUNCTION_CODE (callee)); + break; + + case BUILT_IN_STRCPY_CHK: + case BUILT_IN_STPCPY_CHK: + if (val[1] && is_gimple_val (val[1])) + result = fold_builtin_stxcpy_chk (callee, arglist, val[1], ignore, + DECL_FUNCTION_CODE (callee)); + break; + + case BUILT_IN_STRNCPY_CHK: + if (val[2] && is_gimple_val (val[2])) + result = fold_builtin_strncpy_chk (arglist, val[2]); + break; + + case BUILT_IN_SNPRINTF_CHK: + case BUILT_IN_VSNPRINTF_CHK: + if (val[1] && is_gimple_val (val[1])) + result = fold_builtin_snprintf_chk (arglist, val[1], + DECL_FUNCTION_CODE (callee)); break; default: @@ -2338,18 +2389,26 @@ execute_fold_all_builtins (void) FOR_EACH_BB (bb) { block_stmt_iterator i; - for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i)) + for (i = bsi_start (bb); !bsi_end_p (i); ) { tree *stmtp = bsi_stmt_ptr (i); tree old_stmt = *stmtp; tree call = get_rhs (*stmtp); tree callee, result; + enum built_in_function fcode; if (!call || TREE_CODE (call) != CALL_EXPR) - continue; + { + bsi_next (&i); + continue; + } callee = get_callee_fndecl (call); if (!callee || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL) - continue; + { + bsi_next (&i); + continue; + } + fcode = DECL_FUNCTION_CODE (callee); result = ccp_fold_builtin (*stmtp, call); if (!result) @@ -2363,6 +2422,7 @@ execute_fold_all_builtins (void) break; default: + bsi_next (&i); continue; } @@ -2393,6 +2453,20 @@ execute_fold_all_builtins (void) print_generic_stmt (dump_file, *stmtp, dump_flags); fprintf (dump_file, "\n"); } + + /* Retry the same statement if it changed into another + builtin, there might be new opportunities now. */ + call = get_rhs (*stmtp); + if (!call || TREE_CODE (call) != CALL_EXPR) + { + bsi_next (&i); + continue; + } + callee = get_callee_fndecl (call); + if (!callee + || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL + || DECL_FUNCTION_CODE (callee) == fcode) + bsi_next (&i); } } |