summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/builtins.c68
-rw-r--r--gcc/builtins.def1
-rw-r--r--gcc/c-common.c6
4 files changed, 62 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2fd3cba4c8f..c9a05bb669b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2000-09-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * builtins.c (expand_builtin_fputs): Also expand when length!=1.
+ (expand_builtin): Handle BUILT_IN_FWRITE.
+
+ * builtins.def (BUILT_IN_FWRITE): New entry.
+
+ * c-common.c (c_common_nodes_and_builtins): Declare __builtin_fwrite.
+
Wed Sep 20 15:39:14 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* gcc.c (modify_target): New variable and struct.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 05297230825..4f03dc7f8cb 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -2329,12 +2329,12 @@ expand_builtin_fputs (arglist, ignore)
tree arglist;
int ignore;
{
- tree call_expr, len, stripped_string, newarglist;
- tree fn = built_in_decls[BUILT_IN_FPUTC];
+ tree call_expr, len, fn, fn_fputc = built_in_decls[BUILT_IN_FPUTC],
+ fn_fwrite = built_in_decls[BUILT_IN_FWRITE];
/* If the return value is used, or the replacement _DECL isn't
initialized, don't do the transformation. */
- if (!ignore || !fn)
+ if (!ignore || !fn_fputc || !fn_fwrite)
return 0;
/* Verify the arguments in the original call. */
@@ -2345,29 +2345,54 @@ expand_builtin_fputs (arglist, ignore)
!= POINTER_TYPE))
return 0;
- /* Get the length of the string passed to fputs. */
- len = c_strlen (TREE_VALUE (arglist));
-
- /* If the length != 1, punt. */
- if (len == 0 || compare_tree_int (len, 1))
+ /* Get the length of the string passed to fputs. If the length
+ can't be determined, punt. */
+ if (!(len = c_strlen (TREE_VALUE (arglist))))
return 0;
- stripped_string = TREE_VALUE (arglist);
- STRIP_NOPS (stripped_string);
- if (stripped_string && TREE_CODE (stripped_string) == ADDR_EXPR)
- stripped_string = TREE_OPERAND (stripped_string, 0);
+ switch (compare_tree_int (len, 1))
+ {
+ case -1: /* length is 0, delete the call entirely . */
+ return const0_rtx;
+ case 0: /* length is 1, call fputc. */
+ {
+ tree stripped_string = TREE_VALUE (arglist);
- /* New argument list transforming fputs(string, stream) to
- fputc(string[0], stream). */
- newarglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
- newarglist =
- tree_cons (NULL_TREE,
- build_int_2 (TREE_STRING_POINTER (stripped_string)[0], 0),
- newarglist);
+ STRIP_NOPS (stripped_string);
+ if (stripped_string && TREE_CODE (stripped_string) == ADDR_EXPR)
+ stripped_string = TREE_OPERAND (stripped_string, 0);
+
+ /* New argument list transforming fputs(string, stream) to
+ fputc(string[0], stream). */
+ arglist =
+ build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
+ arglist =
+ tree_cons (NULL_TREE,
+ build_int_2 (TREE_STRING_POINTER (stripped_string)[0], 0),
+ arglist);
+ fn = fn_fputc;
+ break;
+ }
+ case 1: /* length is greater than 1, call fwrite. */
+ {
+ tree string_arg = TREE_VALUE (arglist);
+
+ /* New argument list transforming fputs(string, stream) to
+ fwrite(string, 1, len, stream). */
+ arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
+ arglist = tree_cons (NULL_TREE, len, arglist);
+ arglist = tree_cons (NULL_TREE, integer_one_node, arglist);
+ arglist = tree_cons (NULL_TREE, string_arg, arglist);
+ fn = fn_fwrite;
+ break;
+ }
+ default:
+ abort();
+ }
call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
- call_expr, newarglist, NULL_TREE);
+ call_expr, arglist, NULL_TREE);
TREE_SIDE_EFFECTS (call_expr) = 1;
return expand_expr (call_expr, (ignore ? const0_rtx : NULL_RTX),
VOIDmode, EXPAND_NORMAL);
@@ -2563,7 +2588,7 @@ expand_builtin (exp, target, subtarget, mode, ignore)
|| fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS
|| fcode == BUILT_IN_PUTCHAR || fcode == BUILT_IN_PUTS
|| fcode == BUILT_IN_PRINTF || fcode == BUILT_IN_FPUTC
- || fcode == BUILT_IN_FPUTS))
+ || fcode == BUILT_IN_FPUTS || fcode == BUILT_IN_FWRITE))
return expand_call (exp, target, ignore);
switch (fcode)
@@ -2779,6 +2804,7 @@ expand_builtin (exp, target, subtarget, mode, ignore)
case BUILT_IN_PUTCHAR:
case BUILT_IN_PUTS:
case BUILT_IN_FPUTC:
+ case BUILT_IN_FWRITE:
break;
case BUILT_IN_FPUTS:
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 7220cf9124c..ede0d2e0634 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -64,6 +64,7 @@ DEF_BUILTIN(BUILT_IN_PUTS)
DEF_BUILTIN(BUILT_IN_PRINTF)
DEF_BUILTIN(BUILT_IN_FPUTC)
DEF_BUILTIN(BUILT_IN_FPUTS)
+DEF_BUILTIN(BUILT_IN_FWRITE)
/* ISO C99 floating point unordered comparisons. */
DEF_BUILTIN(BUILT_IN_ISGREATER)
diff --git a/gcc/c-common.c b/gcc/c-common.c
index fec74eb69ef..ce0b33ad788 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -4014,7 +4014,7 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins)
tree endlink, int_endlink, double_endlink, unsigned_endlink;
tree sizetype_endlink;
tree ptr_ftype, ptr_ftype_unsigned;
- tree void_ftype_any, void_ftype_int, int_ftype_any;
+ tree void_ftype_any, void_ftype_int, int_ftype_any, sizet_ftype_any;
tree double_ftype_double, double_ftype_double_double;
tree float_ftype_float, ldouble_ftype_ldouble;
tree int_ftype_cptr_cptr_sizet;
@@ -4060,6 +4060,7 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins)
/* We realloc here because sizetype could be int or unsigned. S'ok. */
ptr_ftype_sizetype = build_function_type (ptr_type_node, sizetype_endlink);
+ sizet_ftype_any = build_function_type (sizetype, NULL_TREE);
int_ftype_any = build_function_type (integer_type_node, NULL_TREE);
void_ftype_any = build_function_type (void_type_node, NULL_TREE);
void_ftype = build_function_type (void_type_node, endlink);
@@ -4377,6 +4378,9 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins)
them later with argument without worrying about the explicit
declarations in stdio.h being taken as the initial declaration.
Also, save the _DECL for these so we can use them later. */
+ built_in_decls[BUILT_IN_FWRITE] =
+ builtin_function ("__builtin_fwrite", sizet_ftype_any,
+ BUILT_IN_FWRITE, BUILT_IN_NORMAL, "fwrite");
built_in_decls[BUILT_IN_FPUTC] =
builtin_function ("__builtin_fputc", int_ftype_any,
BUILT_IN_FPUTC, BUILT_IN_NORMAL, "fputc");