OSDN Git Service

* doc/invoke.texi: Add mcmodel to powerpc options.
[pf3gnuchains/gcc-fork.git] / gcc / genrecog.c
index a65137a..26c2a95 100644 (file)
@@ -1,12 +1,13 @@
 /* Generate code from machine description to recognize rtl as insns.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+   Free Software Foundation, Inc.
 
    This file is part of GCC.
 
    GCC is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GCC is distributed in the hope that it will be useful, but WITHOUT
@@ -15,9 +16,8 @@
    License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GCC; see the file COPYING.  If not, write to the Free
-   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.  */
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
 
 
 /* This program is used to produce insn-recog.c, which contains a
@@ -56,6 +56,7 @@
 #include "tm.h"
 #include "rtl.h"
 #include "errors.h"
+#include "read-md.h"
 #include "gensupport.h"
 
 #define OUTPUT_LABEL(INDENT_STRING, LABEL_NUMBER) \
@@ -71,6 +72,17 @@ struct decision_head
   struct decision *last;
 };
 
+/* These types are roughly in the order in which we'd like to test them.  */
+enum decision_type
+{
+  DT_num_insns,
+  DT_mode, DT_code, DT_veclen,
+  DT_elt_zero_int, DT_elt_one_int, DT_elt_zero_wide, DT_elt_zero_wide_safe,
+  DT_const_int,
+  DT_veclen_ge, DT_dup, DT_pred, DT_c_test,
+  DT_accept_op, DT_accept_insn
+};
+
 /* A single test.  The two accept types aren't tests per-se, but
    their equality (or lack thereof) does affect tree merging so
    it is convenient to keep them here.  */
@@ -80,16 +92,7 @@ struct decision_test
   /* A linked list through the tests attached to a node.  */
   struct decision_test *next;
 
-  /* These types are roughly in the order in which we'd like to test them.  */
-  enum decision_type
-    {
-      DT_num_insns,
-      DT_mode, DT_code, DT_veclen,
-      DT_elt_zero_int, DT_elt_one_int, DT_elt_zero_wide, DT_elt_zero_wide_safe,
-      DT_const_int,
-      DT_veclen_ge, DT_dup, DT_pred, DT_c_test,
-      DT_accept_op, DT_accept_insn
-    } type;
+  enum decision_type type;
 
   union
   {
@@ -167,11 +170,8 @@ static int max_depth;
 
 /* The line number of the start of the pattern currently being processed.  */
 static int pattern_lineno;
-
-/* Count of errors.  */
-static int error_count;
 \f
-/* Predicate handling. 
+/* Predicate handling.
 
    We construct from the machine description a table mapping each
    predicate to a list of the rtl codes it can possibly match.  The
@@ -259,7 +259,7 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
       break;
 
     case IF_THEN_ELSE:
-      /* a ? b : c  accepts the same codes as (a & b) | (!a & c).  */ 
+      /* a ? b : c  accepts the same codes as (a & b) | (!a & c).  */
       compute_predicate_codes (XEXP (exp, 0), op0_codes);
       compute_predicate_codes (XEXP (exp, 1), op1_codes);
       compute_predicate_codes (XEXP (exp, 2), op2_codes);
@@ -286,8 +286,7 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
 
        if (*next_code == '\0')
          {
-           message_with_line (pattern_lineno, "empty match_code expression");
-           error_count++;
+           error_with_line (pattern_lineno, "empty match_code expression");
            break;
          }
 
@@ -295,7 +294,7 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
          {
            size_t n = next_code - code;
            int found_it = 0;
-           
+
            for (i = 0; i < NUM_RTX_CODE; i++)
              if (!strncmp (code, GET_RTX_NAME (i), n)
                  && GET_RTX_NAME (i)[n] == '\0')
@@ -306,9 +305,9 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
                }
            if (!found_it)
              {
-               message_with_line (pattern_lineno, "match_code \"%.*s\" matches nothing",
-                                  (int) n, code);
-               error_count ++;
+               error_with_line (pattern_lineno,
+                                "match_code \"%.*s\" matches nothing",
+                                (int) n, code);
                for (i = 0; i < NUM_RTX_CODE; i++)
                  if (!strncasecmp (code, GET_RTX_NAME (i), n)
                      && GET_RTX_NAME (i)[n] == '\0'
@@ -330,10 +329,9 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
        struct pred_data *p = lookup_predicate (XSTR (exp, 1));
        if (!p)
          {
-           message_with_line (pattern_lineno,
-                              "reference to unknown predicate '%s'",
-                              XSTR (exp, 1));
-           error_count++;
+           error_with_line (pattern_lineno,
+                            "reference to unknown predicate '%s'",
+                            XSTR (exp, 1));
            break;
          }
        for (i = 0; i < NUM_RTX_CODE; i++)
@@ -348,10 +346,9 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
       break;
 
     default:
-      message_with_line (pattern_lineno,
-        "'%s' cannot be used in a define_predicate expression",
-        GET_RTX_NAME (GET_CODE (exp)));
-      error_count++;
+      error_with_line (pattern_lineno,
+                      "'%s' cannot be used in a define_predicate expression",
+                      GET_RTX_NAME (GET_CODE (exp)));
       memset (codes, I, NUM_RTX_CODE);
       break;
     }
@@ -366,9 +363,8 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
 static void
 process_define_predicate (rtx desc)
 {
-  struct pred_data *pred = xcalloc (sizeof (struct pred_data), 1);
+  struct pred_data *pred = XCNEW (struct pred_data);
   char codes[NUM_RTX_CODE];
-  bool seen_one = false;
   int i;
 
   pred->name = XSTR (desc, 0);
@@ -379,26 +375,8 @@ process_define_predicate (rtx desc)
 
   for (i = 0; i < NUM_RTX_CODE; i++)
     if (codes[i] != N)
-      {
-       pred->codes[i] = true;
-       if (GET_RTX_CLASS (i) != RTX_CONST_OBJ)
-         pred->allows_non_const = true;
-       if (i != REG
-           && i != SUBREG
-           && i != MEM
-           && i != CONCAT
-           && i != PARALLEL
-           && i != STRICT_LOW_PART)
-         pred->allows_non_lvalue = true;
-
-       if (seen_one)
-         pred->singleton = UNKNOWN;
-       else
-         {
-           pred->singleton = i;
-           seen_one = true;
-         }
-      }
+      add_predicate_code (pred, (enum rtx_code) i);
+
   add_predicate (pred);
 }
 #undef I
@@ -493,14 +471,14 @@ extern void debug_decision_list
 static struct decision *
 new_decision (const char *position, struct decision_head *last)
 {
-  struct decision *new = xcalloc (1, sizeof (struct decision));
+  struct decision *new_decision = XCNEW (struct decision);
 
-  new->success = *last;
-  new->position = xstrdup (position);
-  new->number = next_number++;
+  new_decision->success = *last;
+  new_decision->position = xstrdup (position);
+  new_decision->number = next_number++;
 
-  last->first = last->last = new;
-  return new;
+  last->first = last->last = new_decision;
+  return new_decision;
 }
 
 /* Create a new test and link it in at PLACE.  */
@@ -650,12 +628,9 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
     case MATCH_OP_DUP:
     case MATCH_PAR_DUP:
       if (find_operand (insn, XINT (pattern, 0), pattern) == pattern)
-       {
-         message_with_line (pattern_lineno,
-                            "operand %i duplicated before defined",
-                            XINT (pattern, 0));
-          error_count++;
-       }
+       error_with_line (pattern_lineno,
+                        "operand %i duplicated before defined",
+                        XINT (pattern, 0));
       break;
     case MATCH_OPERAND:
     case MATCH_OPERATOR:
@@ -711,20 +686,14 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
                             && find_matching_operand (insn, XINT (pattern, 0)))
                      ;
                    else
-                     {
-                       message_with_line (pattern_lineno,
-                                          "operand %d missing in-out reload",
-                                          XINT (pattern, 0));
-                       error_count++;
-                     }
-                 }
-               else if (constraints0 != '=' && constraints0 != '+')
-                 {
-                   message_with_line (pattern_lineno,
-                                      "operand %d missing output reload",
+                     error_with_line (pattern_lineno,
+                                      "operand %d missing in-out reload",
                                       XINT (pattern, 0));
-                   error_count++;
                  }
+               else if (constraints0 != '=' && constraints0 != '+')
+                 error_with_line (pattern_lineno,
+                                  "operand %d missing output reload",
+                                  XINT (pattern, 0));
              }
          }
 
@@ -798,12 +767,9 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
         /* The operands of a SET must have the same mode unless one
           is VOIDmode.  */
         else if (dmode != VOIDmode && smode != VOIDmode && dmode != smode)
-         {
-           message_with_line (pattern_lineno,
-                              "mode mismatch in set: %smode vs %smode",
-                              GET_MODE_NAME (dmode), GET_MODE_NAME (smode));
-           error_count++;
-         }
+         error_with_line (pattern_lineno,
+                          "mode mismatch in set: %smode vs %smode",
+                          GET_MODE_NAME (dmode), GET_MODE_NAME (smode));
 
        /* If only one of the operands is VOIDmode, and PC or CC0 is
           not involved, it's probably a mistake.  */
@@ -812,7 +778,8 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
                 && GET_CODE (dest) != CC0
                 && GET_CODE (src) != PC
                 && GET_CODE (src) != CC0
-                && GET_CODE (src) != CONST_INT)
+                && !CONST_INT_P (src)
+                && GET_CODE (src) != CALL)
          {
            const char *which;
            which = (dmode == VOIDmode ? "destination" : "source");
@@ -843,12 +810,9 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
 
     case LABEL_REF:
       if (GET_MODE (XEXP (pattern, 0)) != VOIDmode)
-       {
-         message_with_line (pattern_lineno,
-                            "operand to label_ref %smode not VOIDmode",
-                            GET_MODE_NAME (GET_MODE (XEXP (pattern, 0))));
-         error_count++;
-       }
+       error_with_line (pattern_lineno,
+                        "operand to label_ref %smode not VOIDmode",
+                        GET_MODE_NAME (GET_MODE (XEXP (pattern, 0))));
       break;
 
     default:
@@ -896,7 +860,7 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
                 enum routine_type insn_type, int top)
 {
   RTX_CODE code;
-  struct decision *this, *sub;
+  struct decision *this_decision, *sub;
   struct decision_test *test;
   struct decision_test **place;
   char *subpos;
@@ -909,12 +873,12 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
   if (depth > max_depth)
     max_depth = depth;
 
-  subpos = xmalloc (depth + 2);
+  subpos = XNEWVAR (char, depth + 2);
   strcpy (subpos, position);
   subpos[depth + 1] = 0;
 
-  sub = this = new_decision (position, last);
-  place = &this->tests;
+  sub = this_decision = new_decision (position, last);
+  place = &this_decision->tests;
 
  restart:
   mode = GET_MODE (pattern);
@@ -1088,7 +1052,7 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
       if (fmt[i] == 'i')
        {
          gcc_assert (i < 2);
-         
+
          if (!i)
            {
              test = new_decision_test (DT_elt_zero_int, &place);
@@ -1161,20 +1125,20 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
      before any of the nodes we may have added above.  */
   if (code != UNKNOWN)
     {
-      place = &this->tests;
+      place = &this_decision->tests;
       test = new_decision_test (DT_code, &place);
       test->u.code = code;
     }
 
   if (mode != VOIDmode)
     {
-      place = &this->tests;
+      place = &this_decision->tests;
       test = new_decision_test (DT_mode, &place);
       test->u.mode = mode;
     }
 
   /* If we didn't insert any tests or accept nodes, hork.  */
-  gcc_assert (this->tests);
+  gcc_assert (this_decision->tests);
 
  ret:
   free (subpos);
@@ -1262,7 +1226,7 @@ maybe_both_true_2 (struct decision_test *d1, struct decision_test *d2)
          else if (d2->type == DT_pred && d2->u.pred.data)
            {
              bool common = false;
-             enum rtx_code c;
+             int c;
 
              for (c = 0; c < NUM_RTX_CODE; c++)
                if (d1->u.pred.data->codes[c] && d2->u.pred.data->codes[c])
@@ -1509,12 +1473,11 @@ merge_accept_insn (struct decision *oldd, struct decision *addd)
     }
   else
     {
-      message_with_line (add->u.insn.lineno, "`%s' matches `%s'",
-                        get_insn_name (add->u.insn.code_number),
-                        get_insn_name (old->u.insn.code_number));
+      error_with_line (add->u.insn.lineno, "`%s' matches `%s'",
+                      get_insn_name (add->u.insn.code_number),
+                      get_insn_name (old->u.insn.code_number));
       message_with_line (old->u.insn.lineno, "previous definition of `%s'",
                         get_insn_name (old->u.insn.code_number));
-      error_count++;
     }
 }
 
@@ -1611,7 +1574,7 @@ factor_tests (struct decision_head *head)
   for (first = head->first; first && first->next; first = next)
     {
       enum decision_type type;
-      struct decision *new, *old_last;
+      struct decision *new_dec, *old_last;
 
       type = first->tests->type;
       next = first->next;
@@ -1634,8 +1597,8 @@ factor_tests (struct decision_head *head)
          below our first test.  */
       if (first->tests->next != NULL)
        {
-         new = new_decision (first->position, &first->success);
-         new->tests = first->tests->next;
+         new_dec = new_decision (first->position, &first->success);
+         new_dec->tests = first->tests->next;
          first->tests->next = NULL;
        }
 
@@ -1652,14 +1615,14 @@ factor_tests (struct decision_head *head)
 
          if (next->tests->next != NULL)
            {
-             new = new_decision (next->position, &next->success);
-             new->tests = next->tests->next;
+             new_dec = new_decision (next->position, &next->success);
+             new_dec->tests = next->tests->next;
              next->tests->next = NULL;
            }
-         new = next;
+         new_dec = next;
          next = next->next;
-         new->next = NULL;
-         h.first = h.last = new;
+         new_dec->next = NULL;
+         h.first = h.last = new_dec;
 
          merge_trees (head, &h);
        }
@@ -1940,7 +1903,8 @@ write_switch (struct decision *start, int depth)
       while (p && p->tests->type == DT_pred && p->tests->u.pred.data)
        {
          const struct pred_data *data = p->tests->u.pred.data;
-         RTX_CODE c;
+         int c;
+
          for (c = 0; c < NUM_RTX_CODE; c++)
            if (codemap[c] && data->codes[c])
              goto pred_done;
@@ -1949,7 +1913,7 @@ write_switch (struct decision *start, int depth)
            if (data->codes[c])
              {
                fputs ("    case ", stdout);
-               print_code (c);
+               print_code ((enum rtx_code) c);
                fputs (":\n", stdout);
                codemap[c] = 1;
              }
@@ -2489,13 +2453,13 @@ write_header (void)
 #include \"function.h\"\n\
 #include \"insn-config.h\"\n\
 #include \"recog.h\"\n\
-#include \"real.h\"\n\
 #include \"output.h\"\n\
 #include \"flags.h\"\n\
 #include \"hard-reg-set.h\"\n\
 #include \"resource.h\"\n\
 #include \"toplev.h\"\n\
 #include \"reload.h\"\n\
+#include \"regs.h\"\n\
 #include \"tm-constrs.h\"\n\
 \n");
 
@@ -2636,25 +2600,25 @@ make_insn_sequence (rtx insn, enum routine_type type)
 
          if (i != XVECLEN (x, 0))
            {
-             rtx new;
+             rtx new_rtx;
              struct decision_head clobber_head;
 
              /* Build a similar insn without the clobbers.  */
              if (i == 1)
-               new = XVECEXP (x, 0, 0);
+               new_rtx = XVECEXP (x, 0, 0);
              else
                {
                  int j;
 
-                 new = rtx_alloc (PARALLEL);
-                 XVEC (new, 0) = rtvec_alloc (i);
+                 new_rtx = rtx_alloc (PARALLEL);
+                 XVEC (new_rtx, 0) = rtvec_alloc (i);
                  for (j = i - 1; j >= 0; j--)
-                   XVECEXP (new, 0, j) = XVECEXP (x, 0, j);
+                   XVECEXP (new_rtx, 0, j) = XVECEXP (x, 0, j);
                }
 
              /* Recognize it.  */
              memset (&clobber_head, 0, sizeof(clobber_head));
-             last = add_to_sequence (new, &clobber_head, "", type, 1);
+             last = add_to_sequence (new_rtx, &clobber_head, "", type, 1);
 
              /* Find the end of the test chain on the last node.  */
              for (test = last->tests; test->next; test = test->next)
@@ -2744,7 +2708,7 @@ main (int argc, char **argv)
   memset (&split_tree, 0, sizeof split_tree);
   memset (&peephole2_tree, 0, sizeof peephole2_tree);
 
-  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+  if (!init_rtx_reader_args (argc, argv))
     return (FATAL_EXIT_CODE);
 
   next_insn_code = 0;
@@ -2785,7 +2749,7 @@ main (int argc, char **argv)
        }
     }
 
-  if (error_count || have_error)
+  if (have_error)
     return FATAL_EXIT_CODE;
 
   puts ("\n\n");
@@ -2912,13 +2876,13 @@ debug_decision_0 (struct decision *d, int indent, int maxdepth)
     debug_decision_0 (n, indent + 2, maxdepth - 1);
 }
 
-void
+DEBUG_FUNCTION void
 debug_decision (struct decision *d)
 {
   debug_decision_0 (d, 0, 1000000);
 }
 
-void
+DEBUG_FUNCTION void
 debug_decision_list (struct decision *d)
 {
   while (d)