diff options
author | Kaveh R. Ghazi <ghazi@caip.rutgers.edu> | 2000-09-12 15:10:50 +0000 |
---|---|---|
committer | Kaveh Ghazi <ghazi@gcc.gnu.org> | 2000-09-12 15:10:50 +0000 |
commit | 3ff5f682dc883c9508606535cd3ec981ac151362 (patch) | |
tree | 81ed5460f20e5d5f8b0cf6d084e31c932f791371 /gcc | |
parent | 208b0ab1c8273e0944e240e42c65dc309bc1b6b7 (diff) | |
download | gcc-3ff5f682dc883c9508606535cd3ec981ac151362.tar.gz |
builtins.c (built_in_decls): New array.
* builtins.c (built_in_decls): New array.
(expand_builtin_fputs): New function.
(expand_builtin): Handle BUILT_IN_FPUTC and BUILT_IN_FPUTS.
* builtins.def (BUILT_IN_FPUTC, BUILT_IN_FPUTS): New members.
* c-common.c (c_common_nodes_and_builtins): Handle fputc/fputs.
* tree.h (built_in_decls): New array.
From-SVN: r36363
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/builtins.c | 76 | ||||
-rw-r--r-- | gcc/builtins.def | 4 | ||||
-rw-r--r-- | gcc/c-common.c | 20 | ||||
-rw-r--r-- | gcc/tree.h | 3 |
5 files changed, 114 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 03a1600e3ac..642d2374290 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2000-09-12 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * builtins.c (built_in_decls): New array. + (expand_builtin_fputs): New function. + (expand_builtin): Handle BUILT_IN_FPUTC and BUILT_IN_FPUTS. + + * builtins.def (BUILT_IN_FPUTC, BUILT_IN_FPUTS): New members. + + * c-common.c (c_common_nodes_and_builtins): Handle fputc/fputs. + + * tree.h (built_in_decls): New array. + Tue Sep 12 08:53:57 2000 Jeffrey A Law (law@cygnus.com) * convex.md: Use "+" instead of "=" for outputs wrapped in a diff --git a/gcc/builtins.c b/gcc/builtins.c index 4f3f7a9fd24..cc818977b47 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -67,6 +67,15 @@ const char *const built_in_names[(int) END_BUILTINS] = }; #undef DEF_BUILTIN +/* Setup an array of _DECL trees, make sure each element is + initialized to NULL_TREE. */ +#define DEF_BUILTIN(x) NULL_TREE, +tree built_in_decls[(int) END_BUILTINS] = +{ +#include "builtins.def" +}; +#undef DEF_BUILTIN + tree (*lang_type_promotes_to) PARAMS ((tree)); static int get_pointer_alignment PARAMS ((tree, unsigned)); @@ -102,6 +111,7 @@ static rtx expand_builtin_strlen PARAMS ((tree, rtx, static rtx expand_builtin_alloca PARAMS ((tree, rtx)); static rtx expand_builtin_ffs PARAMS ((tree, rtx, rtx)); static rtx expand_builtin_frame_address PARAMS ((tree)); +static rtx expand_builtin_fputs PARAMS ((tree, int)); static tree stabilize_va_list PARAMS ((tree, int)); static rtx expand_builtin_expect PARAMS ((tree, rtx)); @@ -2310,6 +2320,60 @@ expand_builtin_ffs (arglist, target, subtarget) return target; } +/* If the string passed to fputs is a constant and is one character + long, we attempt to transform this call into __builtin_fputc(). */ +static rtx +expand_builtin_fputs (arglist, ignore) + tree arglist; + int ignore; +{ + tree call_expr, len, stripped_string, newarglist; + tree fn = built_in_decls[BUILT_IN_FPUTC]; + + /* If the return value is used, or the replacement _DECL isn't + initialized, don't do the transformation. */ + if (!ignore || !fn) + return 0; + + /* Verify the arguments in the original call. */ + if (arglist == 0 + || (TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE) + || TREE_CHAIN (arglist) == 0 + || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) + != 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)) + 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); + + /* 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); + +#ifdef TEST_STDIO_OPTS + warning ("Converted fputs(one-char-string, FILE*) -> fputc(char, FILE*)"); +#endif + + 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); + TREE_SIDE_EFFECTS (call_expr) = 1; + return expand_expr (call_expr, NULL_RTX, VOIDmode, 0); +} + /* Expand a call to __builtin_expect. We return our argument and emit a NOTE_INSN_EXPECTED_VALUE note. */ @@ -2383,7 +2447,8 @@ expand_builtin (exp, target, subtarget, mode, ignore) || fcode == BUILT_IN_MEMCPY || fcode == BUILT_IN_MEMCMP || fcode == BUILT_IN_BCMP || fcode == BUILT_IN_BZERO || fcode == BUILT_IN_STRLEN || fcode == BUILT_IN_STRCPY - || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS)) + || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS + || fcode == BUILT_IN_FPUTC || fcode == BUILT_IN_FPUTS)) return expand_call (exp, target, ignore); switch (fcode) @@ -2596,6 +2661,15 @@ expand_builtin (exp, target, subtarget, mode, ignore) emit_barrier (); return const0_rtx; + case BUILT_IN_FPUTC: + break; + + case BUILT_IN_FPUTS: + target = expand_builtin_fputs (arglist, ignore); + if (target) + return target; + break; + /* Various hooks for the DWARF 2 __throw routine. */ case BUILT_IN_UNWIND_INIT: expand_builtin_unwind_init (); diff --git a/gcc/builtins.def b/gcc/builtins.def index 308257fa859..40ae59c3d73 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -58,6 +58,10 @@ DEF_BUILTIN(BUILT_IN_SETJMP) DEF_BUILTIN(BUILT_IN_LONGJMP) DEF_BUILTIN(BUILT_IN_TRAP) + /* Stdio builtins. */ +DEF_BUILTIN(BUILT_IN_FPUTC) +DEF_BUILTIN(BUILT_IN_FPUTS) + /* ISO C99 floating point unordered comparisons. */ DEF_BUILTIN(BUILT_IN_ISGREATER) DEF_BUILTIN(BUILT_IN_ISGREATEREQUAL) diff --git a/gcc/c-common.c b/gcc/c-common.c index 5e093372121..c4efbc81bbe 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -4136,6 +4136,17 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins) BUILT_IN_COS, BUILT_IN_NORMAL, "cos"); builtin_function ("__builtin_cosl", ldouble_ftype_ldouble, BUILT_IN_COS, BUILT_IN_NORMAL, "cosl"); + /* We declare these without argument so that the initial declaration + for these identifiers is a builtin. That allows us to redeclare + 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_FPUTC] = + builtin_function ("__builtin_fputc", int_ftype_any, + BUILT_IN_FPUTC, BUILT_IN_NORMAL, "fputc"); + built_in_decls[BUILT_IN_FPUTS] = + builtin_function ("__builtin_fputs", int_ftype_any, + BUILT_IN_FPUTS, BUILT_IN_NORMAL, "fputs"); if (! no_builtins) { @@ -4179,6 +4190,15 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins) BUILT_IN_NORMAL, NULL_PTR); builtin_function ("cosl", ldouble_ftype_ldouble, BUILT_IN_COS, BUILT_IN_NORMAL, NULL_PTR); + /* We declare these without argument so that the initial + declaration for these identifiers is a builtin. That allows + us to redeclare them later with argument without worrying + about the explicit declarations in stdio.h being taken as the + initial declaration. */ + builtin_function ("fputc", int_ftype_any, BUILT_IN_FPUTC, + BUILT_IN_NORMAL, NULL_PTR); + builtin_function ("fputs", int_ftype_any, BUILT_IN_FPUTS, + BUILT_IN_NORMAL, NULL_PTR); /* Declare these functions volatile to avoid spurious "control drops through" warnings. */ diff --git a/gcc/tree.h b/gcc/tree.h index baf32266661..330e28c16ea 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -96,6 +96,9 @@ enum built_in_function /* Names for the above. */ extern const char *const built_in_names[(int) END_BUILTINS]; + +/* An array of _DECL trees for the above. */ +extern union tree_node *built_in_decls[(int) END_BUILTINS]; /* The definition of tree nodes fills the next several pages. */ |