OSDN Git Service

* builtins.c (built_in_decls): New array.
authorghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Sep 2000 15:10:50 +0000 (15:10 +0000)
committerghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Sep 2000 15:10:50 +0000 (15:10 +0000)
(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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@36363 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/builtins.c
gcc/builtins.def
gcc/c-common.c
gcc/tree.h

index 03a1600..642d237 100644 (file)
@@ -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
index 4f3f7a9..cc81897 100644 (file)
@@ -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 ();
index 308257f..40ae59c 100644 (file)
@@ -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)
index 5e09337..c4efbc8 100644 (file)
@@ -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.  */
index baf3226..330e28c 100644 (file)
@@ -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];
 \f
 /* The definition of tree nodes fills the next several pages.  */