builtins.c (rewrite_call_expr): Move code to...

* builtins.c (rewrite_call_expr): Move code to...
	(rewrite_call_expr_valist): ...here.  Call
	build_call_expr_loc_array.
	(rewrite_call_expr_array): New function.
	(fold_builtin_sprintf_chk_1): New function.
	(fold_builtin_sprintf_chk): Call it.
	(gimple_fold_builtin_sprintf_chk): Likewise.
	(fold_builtin_snprintf_chk_1): New function.
	(fold_builtin_snprintf_chk): Call it.
	(gimple_fold_builtin_snprintf_chk): Likewise.
	(gimple_rewrite_call_expr): Delete.

From-SVN: r165146
This commit is contained in:
Nathan Froyd 2010-10-08 01:06:14 +00:00 committed by Nathan Froyd
parent 937f7f69bc
commit 43ea30dc94
2 changed files with 127 additions and 226 deletions

View File

@ -1,3 +1,17 @@
2010-10-07 Nathan Froyd <froydnj@codesourcery.com>
* builtins.c (rewrite_call_expr): Move code to...
(rewrite_call_expr_valist): ...here. Call
build_call_expr_loc_array.
(rewrite_call_expr_array): New function.
(fold_builtin_sprintf_chk_1): New function.
(fold_builtin_sprintf_chk): Call it.
(gimple_fold_builtin_sprintf_chk): Likewise.
(fold_builtin_snprintf_chk_1): New function.
(fold_builtin_snprintf_chk): Call it.
(gimple_fold_builtin_snprintf_chk): Likewise.
(gimple_rewrite_call_expr): Delete.
2010-10-07 Dave Korn <dave.korn.cygwin@gmail.com>
* config.host: Update copyright year.

View File

@ -10869,6 +10869,53 @@ fold_builtin_call_array (location_t loc, tree type,
return build_call_array_loc (loc, type, fn, n, argarray);
}
/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
list ARGS along with N new arguments in NEWARGS. SKIP is the number
of arguments in ARGS to be omitted. OLDNARGS is the number of
elements in ARGS. */
static tree
rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
int skip, tree fndecl, int n, va_list newargs)
{
int nargs = oldnargs - skip + n;
tree *buffer;
if (n > 0)
{
int i, j;
buffer = XALLOCAVEC (tree, nargs);
for (i = 0; i < n; i++)
buffer[i] = va_arg (newargs, tree);
for (j = skip; j < oldnargs; j++, i++)
buffer[i] = args[j];
}
else
buffer = args + skip;
return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
}
/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
list ARGS along with N new arguments specified as the "..."
parameters. SKIP is the number of arguments in ARGS to be omitted.
OLDNARGS is the number of elements in ARGS. */
static tree
rewrite_call_expr_array (location_t loc, int oldnargs, tree *args,
int skip, tree fndecl, int n, ...)
{
va_list ap;
tree t;
va_start (ap, n);
t = rewrite_call_expr_valist (loc, oldnargs, args, skip, fndecl, n, ap);
va_end (ap);
return t;
}
/* Construct a new CALL_EXPR using the tail of the argument list of EXP
along with N new arguments specified as the "..." parameters. SKIP
is the number of arguments in EXP to be omitted. This function is used
@ -10877,29 +10924,15 @@ fold_builtin_call_array (location_t loc, tree type,
static tree
rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
{
int oldnargs = call_expr_nargs (exp);
int nargs = oldnargs - skip + n;
tree fntype = TREE_TYPE (fndecl);
tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
tree *buffer;
va_list ap;
tree t;
if (n > 0)
{
int i, j;
va_list ap;
va_start (ap, n);
t = rewrite_call_expr_valist (loc, call_expr_nargs (exp),
CALL_EXPR_ARGP (exp), skip, fndecl, n, ap);
va_end (ap);
buffer = XALLOCAVEC (tree, nargs);
va_start (ap, n);
for (i = 0; i < n; i++)
buffer[i] = va_arg (ap, tree);
va_end (ap);
for (j = skip; j < oldnargs; j++, i++)
buffer[i] = CALL_EXPR_ARG (exp, j);
}
else
buffer = CALL_EXPR_ARGP (exp) + skip;
return fold (build_call_array_loc (loc, TREE_TYPE (exp), fn, nargs, buffer));
return t;
}
/* Validate a single argument ARG against a tree code CODE representing
@ -12460,31 +12493,31 @@ fold_builtin_strncat_chk (location_t loc, tree fndecl,
return build_call_expr_loc (loc, fn, 3, dest, src, len);
}
/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if
a normal call should be emitted rather than expanding the function
inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
/* Fold a call EXP to __{,v}sprintf_chk having NARGS passed as ARGS.
Return NULL_TREE if a normal call should be emitted rather than
expanding the function inline. FCODE is either BUILT_IN_SPRINTF_CHK
or BUILT_IN_VSPRINTF_CHK. */
static tree
fold_builtin_sprintf_chk (location_t loc, tree exp,
enum built_in_function fcode)
fold_builtin_sprintf_chk_1 (location_t loc, int nargs, tree *args,
enum built_in_function fcode)
{
tree dest, size, len, fn, fmt, flag;
const char *fmt_str;
int nargs = call_expr_nargs (exp);
/* Verify the required arguments in the original call. */
if (nargs < 4)
return NULL_TREE;
dest = CALL_EXPR_ARG (exp, 0);
dest = args[0];
if (!validate_arg (dest, POINTER_TYPE))
return NULL_TREE;
flag = CALL_EXPR_ARG (exp, 1);
flag = args[1];
if (!validate_arg (flag, INTEGER_TYPE))
return NULL_TREE;
size = CALL_EXPR_ARG (exp, 2);
size = args[2];
if (!validate_arg (size, INTEGER_TYPE))
return NULL_TREE;
fmt = CALL_EXPR_ARG (exp, 3);
fmt = args[3];
if (!validate_arg (fmt, POINTER_TYPE))
return NULL_TREE;
@ -12515,7 +12548,7 @@ fold_builtin_sprintf_chk (location_t loc, tree exp,
if (nargs == 5)
{
arg = CALL_EXPR_ARG (exp, 4);
arg = args[4];
if (validate_arg (arg, POINTER_TYPE))
{
len = c_strlen (arg, 1);
@ -12549,38 +12582,50 @@ fold_builtin_sprintf_chk (location_t loc, tree exp,
if (!fn)
return NULL_TREE;
return rewrite_call_expr (loc, exp, 4, fn, 2, dest, fmt);
return rewrite_call_expr_array (loc, nargs, args, 4, fn, 2, dest, fmt);
}
/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if
/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if
a normal call should be emitted rather than expanding the function
inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
static tree
fold_builtin_sprintf_chk (location_t loc, tree exp,
enum built_in_function fcode)
{
return fold_builtin_sprintf_chk_1 (loc, call_expr_nargs (exp),
CALL_EXPR_ARGP (exp), fcode);
}
/* Fold a call EXP to {,v}snprintf having NARGS passed as ARGS. Return
NULL_TREE if a normal call should be emitted rather than expanding
the function inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
passed as second argument. */
tree
fold_builtin_snprintf_chk (location_t loc, tree exp, tree maxlen,
enum built_in_function fcode)
static tree
fold_builtin_snprintf_chk_1 (location_t loc, int nargs, tree *args,
tree maxlen, enum built_in_function fcode)
{
tree dest, size, len, fn, fmt, flag;
const char *fmt_str;
/* Verify the required arguments in the original call. */
if (call_expr_nargs (exp) < 5)
if (nargs < 5)
return NULL_TREE;
dest = CALL_EXPR_ARG (exp, 0);
dest = args[0];
if (!validate_arg (dest, POINTER_TYPE))
return NULL_TREE;
len = CALL_EXPR_ARG (exp, 1);
len = args[1];
if (!validate_arg (len, INTEGER_TYPE))
return NULL_TREE;
flag = CALL_EXPR_ARG (exp, 2);
flag = args[2];
if (!validate_arg (flag, INTEGER_TYPE))
return NULL_TREE;
size = CALL_EXPR_ARG (exp, 3);
size = args[3];
if (!validate_arg (size, INTEGER_TYPE))
return NULL_TREE;
fmt = CALL_EXPR_ARG (exp, 4);
fmt = args[4];
if (!validate_arg (fmt, POINTER_TYPE))
return NULL_TREE;
@ -12626,7 +12671,21 @@ fold_builtin_snprintf_chk (location_t loc, tree exp, tree maxlen,
if (!fn)
return NULL_TREE;
return rewrite_call_expr (loc, exp, 5, fn, 3, dest, len, fmt);
return rewrite_call_expr_array (loc, nargs, args, 5, fn, 3, dest, len, fmt);
}
/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if
a normal call should be emitted rather than expanding the function
inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
passed as second argument. */
tree
fold_builtin_snprintf_chk (location_t loc, tree exp, tree maxlen,
enum built_in_function fcode)
{
return fold_builtin_snprintf_chk_1 (loc, call_expr_nargs (exp),
CALL_EXPR_ARGP (exp), maxlen, fcode);
}
/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
@ -13482,43 +13541,6 @@ do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
return result;
}
/* FIXME tuples.
The functions below provide an alternate interface for folding
builtin function calls presented as GIMPLE_CALL statements rather
than as CALL_EXPRs. The folded result is still expressed as a
tree. There is too much code duplication in the handling of
varargs functions, and a more intrusive re-factoring would permit
better sharing of code between the tree and statement-based
versions of these functions. */
/* Construct a new CALL_EXPR using the tail of the argument list of STMT
along with N new arguments specified as the "..." parameters. SKIP
is the number of arguments in STMT to be omitted. This function is used
to do varargs-to-varargs transformations. */
static tree
gimple_rewrite_call_expr (gimple stmt, int skip, tree fndecl, int n, ...)
{
int oldnargs = gimple_call_num_args (stmt);
int nargs = oldnargs - skip + n;
tree fntype = TREE_TYPE (fndecl);
tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
tree *buffer;
int i, j;
va_list ap;
location_t loc = gimple_location (stmt);
buffer = XALLOCAVEC (tree, nargs);
va_start (ap, n);
for (i = 0; i < n; i++)
buffer[i] = va_arg (ap, tree);
va_end (ap);
for (j = skip; j < oldnargs; j++, i++)
buffer[i] = gimple_call_arg (stmt, j);
return fold (build_call_array_loc (loc, TREE_TYPE (fntype), fn, nargs, buffer));
}
/* Fold a call STMT to __{,v}sprintf_chk. Return NULL_TREE if
a normal call should be emitted rather than expanding the function
inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
@ -13526,88 +13548,12 @@ gimple_rewrite_call_expr (gimple stmt, int skip, tree fndecl, int n, ...)
static tree
gimple_fold_builtin_sprintf_chk (gimple stmt, enum built_in_function fcode)
{
tree dest, size, len, fn, fmt, flag;
const char *fmt_str;
int nargs = gimple_call_num_args (stmt);
/* Verify the required arguments in the original call. */
if (nargs < 4)
return NULL_TREE;
dest = gimple_call_arg (stmt, 0);
if (!validate_arg (dest, POINTER_TYPE))
return NULL_TREE;
flag = gimple_call_arg (stmt, 1);
if (!validate_arg (flag, INTEGER_TYPE))
return NULL_TREE;
size = gimple_call_arg (stmt, 2);
if (!validate_arg (size, INTEGER_TYPE))
return NULL_TREE;
fmt = gimple_call_arg (stmt, 3);
if (!validate_arg (fmt, POINTER_TYPE))
return NULL_TREE;
if (! host_integerp (size, 1))
return NULL_TREE;
len = NULL_TREE;
if (!init_target_chars ())
return NULL_TREE;
/* Check whether the format is a literal string constant. */
fmt_str = c_getstr (fmt);
if (fmt_str != NULL)
{
/* If the format doesn't contain % args or %%, we know the size. */
if (strchr (fmt_str, target_percent) == 0)
{
if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
len = build_int_cstu (size_type_node, strlen (fmt_str));
}
/* If the format is "%s" and first ... argument is a string literal,
we know the size too. */
else if (fcode == BUILT_IN_SPRINTF_CHK
&& strcmp (fmt_str, target_percent_s) == 0)
{
tree arg;
if (nargs == 5)
{
arg = gimple_call_arg (stmt, 4);
if (validate_arg (arg, POINTER_TYPE))
{
len = c_strlen (arg, 1);
if (! len || ! host_integerp (len, 1))
len = NULL_TREE;
}
}
}
}
if (! integer_all_onesp (size))
{
if (! len || ! tree_int_cst_lt (len, size))
return NULL_TREE;
}
/* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
or if format doesn't contain % chars or is "%s". */
if (! integer_zerop (flag))
{
if (fmt_str == NULL)
return NULL_TREE;
if (strchr (fmt_str, target_percent) != NULL
&& strcmp (fmt_str, target_percent_s))
return NULL_TREE;
}
/* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
if (!fn)
return NULL_TREE;
return gimple_rewrite_call_expr (stmt, 4, fn, 2, dest, fmt);
return fold_builtin_sprintf_chk_1 (gimple_location (stmt), nargs,
(nargs > 0
? gimple_call_arg_ptr (stmt, 0)
: &error_mark_node), fcode);
}
/* Fold a call STMT to {,v}snprintf. Return NULL_TREE if
@ -13620,71 +13566,12 @@ tree
gimple_fold_builtin_snprintf_chk (gimple stmt, tree maxlen,
enum built_in_function fcode)
{
tree dest, size, len, fn, fmt, flag;
const char *fmt_str;
int nargs = gimple_call_num_args (stmt);
/* Verify the required arguments in the original call. */
if (gimple_call_num_args (stmt) < 5)
return NULL_TREE;
dest = gimple_call_arg (stmt, 0);
if (!validate_arg (dest, POINTER_TYPE))
return NULL_TREE;
len = gimple_call_arg (stmt, 1);
if (!validate_arg (len, INTEGER_TYPE))
return NULL_TREE;
flag = gimple_call_arg (stmt, 2);
if (!validate_arg (flag, INTEGER_TYPE))
return NULL_TREE;
size = gimple_call_arg (stmt, 3);
if (!validate_arg (size, INTEGER_TYPE))
return NULL_TREE;
fmt = gimple_call_arg (stmt, 4);
if (!validate_arg (fmt, POINTER_TYPE))
return NULL_TREE;
if (! host_integerp (size, 1))
return NULL_TREE;
if (! integer_all_onesp (size))
{
if (! host_integerp (len, 1))
{
/* If LEN is not constant, try MAXLEN too.
For MAXLEN only allow optimizing into non-_ocs function
if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
return NULL_TREE;
}
else
maxlen = len;
if (tree_int_cst_lt (size, maxlen))
return NULL_TREE;
}
if (!init_target_chars ())
return NULL_TREE;
/* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
or if format doesn't contain % chars or is "%s". */
if (! integer_zerop (flag))
{
fmt_str = c_getstr (fmt);
if (fmt_str == NULL)
return NULL_TREE;
if (strchr (fmt_str, target_percent) != NULL
&& strcmp (fmt_str, target_percent_s))
return NULL_TREE;
}
/* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
available. */
fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
if (!fn)
return NULL_TREE;
return gimple_rewrite_call_expr (stmt, 5, fn, 3, dest, len, fmt);
return fold_builtin_snprintf_chk_1 (gimple_location (stmt), nargs,
(nargs > 0
? gimple_call_arg_ptr (stmt, 0)
: &error_mark_node), maxlen, fcode);
}
/* Builtins with folding operations that operate on "..." arguments