OSDN Git Service

* simplify-rtx.c (simplify_subreg): Fix verification of
[pf3gnuchains/gcc-fork.git] / gcc / rtl.c
index bb986e9..0fad136 100644 (file)
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -28,6 +28,7 @@ Boston, MA 02111-1307, USA.  */
 #include "ggc.h"
 #include "obstack.h"
 #include "toplev.h"
+#include "hashtab.h"
 
 #define        obstack_chunk_alloc     xmalloc
 #define        obstack_chunk_free      free
@@ -287,13 +288,20 @@ const char * const reg_note_name[] =
   "REG_LABEL", "REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_BR_PROB",
   "REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA", "REG_BR_PRED",
   "REG_FRAME_RELATED_EXPR", "REG_EH_CONTEXT", "REG_EH_REGION",
-  "REG_EH_RETHROW", "REG_SAVE_NOTE", "REG_MAYBE_DEAD", "REG_NORETURN"
+  "REG_EH_RETHROW", "REG_SAVE_NOTE", "REG_MAYBE_DEAD", "REG_NORETURN",
+  "REG_NON_LOCAL_GOTO"
 };
 
+static htab_t md_constants;
+
 static void fatal_with_file_and_line PARAMS ((FILE *, const char *, ...))
   ATTRIBUTE_PRINTF_2 ATTRIBUTE_NORETURN;
 static void fatal_expected_char PARAMS ((FILE *, int, int)) ATTRIBUTE_NORETURN;
 static void read_name          PARAMS ((char *, FILE *));
+static char *read_string       PARAMS ((struct obstack *, FILE *));
+static unsigned def_hash PARAMS ((const void *));
+static int def_name_eq_p PARAMS ((const void *, const void *));
+static void read_constants PARAMS ((FILE *infile, char *tmp_char));
 
 \f
 /* Allocate an rtx vector of N elements.
@@ -479,6 +487,7 @@ copy_most_rtx (orig, may_share)
   copy->volatil = orig->volatil;
   copy->unchanging = orig->unchanging;
   copy->integrated = orig->integrated;
+  copy->frame_related = orig->frame_related;
 
   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
 
@@ -552,6 +561,7 @@ shallow_copy_rtx (orig)
   copy->volatil = orig->volatil;
   copy->unchanging = orig->unchanging;
   copy->integrated = orig->integrated;
+  copy->frame_related = orig->frame_related;
 
   for (i = 0; i < GET_RTX_LENGTH (code); i++)
     copy->fld[i] = orig->fld[i];
@@ -829,6 +839,82 @@ read_name (str, infile)
     read_rtx_lineno++;
 
   *p = 0;
+
+  if (md_constants)
+    {
+      /* Do constant expansion.  */
+      struct md_constant *def;
+
+      p = str;
+      do
+       {
+         struct md_constant tmp_def;
+
+         tmp_def.name = p;
+         def = htab_find (md_constants, &tmp_def);
+         if (def)
+           p = def->value;
+       } while (def);
+      if (p != str)
+       strcpy (str, p);
+    }
+}
+
+/* Read a double-quoted string onto the obstack.  */
+
+static char *
+read_string (ob, infile)
+     struct obstack *ob;
+     FILE *infile;
+{
+  char *stringbuf;
+  int saw_paren = 0;
+  int c;
+
+  c = read_skip_spaces (infile);
+  if (c == '(')
+    {
+      saw_paren = 1;
+      c = read_skip_spaces (infile);
+    }
+  if (c != '"')
+    fatal_expected_char (infile, '"', c);
+
+  while (1)
+    {
+      c = getc (infile); /* Read the string  */
+      if (c == '\n')
+       read_rtx_lineno++;
+      else if (c == '\\')
+       {
+         c = getc (infile);    /* Read the string  */
+         /* \; makes stuff for a C string constant containing
+            newline and tab.  */
+         if (c == ';')
+           {
+             obstack_grow (ob, "\\n\\t", 4);
+             continue;
+           }
+         if (c == '\n')
+           read_rtx_lineno++;
+       }
+      else if (c == '"')
+       break;
+
+      obstack_1grow (ob, c);
+    }
+
+  obstack_1grow (ob, 0);
+  stringbuf = (char *) obstack_finish (ob);
+
+  if (saw_paren)
+    {
+      c = read_skip_spaces (infile);
+      if (c != ')')
+       fatal_expected_char (infile, ')', c);
+    }
+
+  return stringbuf;
 }
 \f
 /* Provide a version of a function to read a long long if the system does
@@ -868,6 +954,98 @@ atoll(p)
 }
 #endif
 
+/* Given a constant definition, return a hash code for its name.  */
+static unsigned
+def_hash (def)
+     const void *def;
+{
+  unsigned result, i;
+  const char *string = ((const struct md_constant *)def)->name;
+
+  for (result = i = 0;*string++ != '\0'; i++)
+    result += ((unsigned char) *string << (i % CHAR_BIT));
+  return result;
+}
+
+/* Given two constant definitions, return true if they have the same name.  */
+static int
+def_name_eq_p (def1, def2)
+     const void *def1, *def2;
+{
+  return ! strcmp (((const struct md_constant *)def1)->name,
+                  ((const struct md_constant *)def2)->name);
+}
+
+/* INFILE is a FILE pointer to read text from.  TMP_CHAR is a buffer suitable
+   to read a name or number into.  Process a define_constants directive,
+   starting with the optional space after the "define_constants".  */
+static void
+read_constants (infile, tmp_char)
+     FILE *infile;
+     char *tmp_char;
+{
+  int c;
+  htab_t defs;
+
+  c = read_skip_spaces (infile);
+  if (c != '[')
+    fatal_expected_char (infile, '[', c);
+  defs = md_constants;
+  if (! defs)
+    defs = htab_create (32, def_hash, def_name_eq_p, (htab_del) 0);
+  /* Disable constant expansion during definition processing.  */
+  md_constants = 0;
+  while ( (c = read_skip_spaces (infile)) != ']')
+    {
+      struct md_constant *def;
+      void **entry_ptr;
+
+      if (c != '(')
+       fatal_expected_char (infile, '(', c);
+      def = xmalloc (sizeof (struct md_constant));
+      def->name = tmp_char;
+      read_name (tmp_char, infile);
+      entry_ptr = htab_find_slot (defs, def, TRUE);
+      if (! *entry_ptr)
+       def->name = xstrdup (tmp_char);
+      c = read_skip_spaces (infile);
+      ungetc (c, infile);
+      read_name (tmp_char, infile);
+      if (! *entry_ptr)
+       {
+         def->value = xstrdup (tmp_char);
+         *entry_ptr = def;
+       }
+      else
+       {
+         def = *entry_ptr;
+         if (strcmp (def->value, tmp_char))
+           fatal_with_file_and_line (infile,
+                                     "redefinition of %s, was %s, now %s",
+                                     def->name, def->value, tmp_char);
+       }
+      c = read_skip_spaces (infile);
+      if (c != ')')
+       fatal_expected_char (infile, ')', c);
+    }
+  md_constants = defs;
+  c = read_skip_spaces (infile);
+  if (c != ')')
+    fatal_expected_char (infile, ')', c);
+}
+
+/* For every constant definition, call CALLBACK with two arguments:
+   a pointer a pointer to the constant definition and INFO.
+   Stops when CALLBACK returns zero.  */
+void
+traverse_md_constants (callback, info)
+     htab_trav callback;
+     void *info;
+{
+  if (md_constants)
+    htab_traverse (md_constants, callback, info);
+}
+
 /* Read an rtx in printed representation from INFILE
    and return an actual rtx in core constructed accordingly.
    read_rtx is not used in the compiler proper, but rather in
@@ -877,7 +1055,7 @@ rtx
 read_rtx (infile)
      FILE *infile;
 {
-  register int i, j, list_counter;
+  register int i, j;
   RTX_CODE tmp_code;
   register const char *format_ptr;
   /* tmp_char is a buffer used for reading decimal integers
@@ -907,6 +1085,7 @@ read_rtx (infile)
     initialized = 1;
   }
 
+again:
   c = read_skip_spaces (infile); /* Should be open paren.  */
   if (c != '(')
     fatal_expected_char (infile, '(', c);
@@ -915,6 +1094,11 @@ read_rtx (infile)
 
   tmp_code = UNKNOWN;
 
+  if (! strcmp (tmp_char, "define_constants"))
+    {
+      read_constants (infile, tmp_char);
+      goto again;
+    }
   for (i = 0; i < NUM_RTX_CODE; i++)
     if (! strcmp (tmp_char, GET_RTX_NAME (i)))
       {
@@ -985,40 +1169,31 @@ read_rtx (infile)
 
       case 'E':
        {
-         register struct rtx_list *next_rtx, *rtx_list_link;
-         struct rtx_list *list_rtx = NULL;
+         /* Obstack to store scratch vector in.  */
+         struct obstack vector_stack;
+         int list_counter = 0;
+         rtvec return_vec = NULL_RTVEC;
 
          c = read_skip_spaces (infile);
          if (c != '[')
            fatal_expected_char (infile, '[', c);
 
          /* add expressions to a list, while keeping a count */
-         next_rtx = NULL;
-         list_counter = 0;
+         obstack_init (&vector_stack);
          while ((c = read_skip_spaces (infile)) && c != ']')
            {
              ungetc (c, infile);
              list_counter++;
-             rtx_list_link = (struct rtx_list *)
-               alloca (sizeof (struct rtx_list));
-             rtx_list_link->value = read_rtx (infile);
-             if (next_rtx == 0)
-               list_rtx = rtx_list_link;
-             else
-               next_rtx->next = rtx_list_link;
-             next_rtx = rtx_list_link;
-             rtx_list_link->next = 0;
+             obstack_ptr_grow (&vector_stack, (PTR) read_rtx (infile));
            }
-         /* get vector length and allocate it */
-         XVEC (return_rtx, i) = (list_counter
-                                 ? rtvec_alloc (list_counter) : NULL_RTVEC);
          if (list_counter > 0)
            {
-             next_rtx = list_rtx;
-             for (j = 0; j < list_counter; j++,
-                  next_rtx = next_rtx->next)
-               XVECEXP (return_rtx, i, j) = next_rtx->value;
+             return_vec = rtvec_alloc (list_counter);
+             memcpy (&return_vec->elem[0], obstack_finish (&vector_stack),
+                     list_counter * sizeof (rtx));
            }
+         XVEC (return_rtx, i) = return_vec;
+         obstack_free (&vector_stack, NULL);
          /* close bracket gotten */
        }
        break;
@@ -1036,51 +1211,32 @@ read_rtx (infile)
 
       case 's':
        {
-         int saw_paren = 0;
-         register char *stringbuf;
-
-         c = read_skip_spaces (infile);
-         if (c == '(')
+         char *stringbuf;
+
+         stringbuf = read_string (&rtl_obstack, infile);
+
+         /* For insn patterns, we want to provide a default name
+            based on the file and line, like "*foo.md:12", if the
+            given name is blank.  These are only for define_insn and
+            define_insn_and_split, to aid debugging.  */
+         if (*stringbuf == '\0'
+             && i == 0
+             && (GET_CODE (return_rtx) == DEFINE_INSN
+                 || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT))
            {
-             saw_paren = 1;
-             c = read_skip_spaces (infile);
+             char line_name[20];
+             const char *fn = (read_rtx_filename ? read_rtx_filename : "rtx");
+             const char *slash;
+             for (slash = fn; *slash; slash ++)
+               if (*slash == '/' || *slash == '\\' || *slash == ':')
+                 fn = slash + 1;
+             obstack_1grow (&rtl_obstack, '*');
+             obstack_grow (&rtl_obstack, fn, strlen (fn));
+             sprintf (line_name, ":%d", read_rtx_lineno);
+             obstack_grow (&rtl_obstack, line_name, strlen (line_name)+1);
+             stringbuf = (char *) obstack_finish (&rtl_obstack);
            }
-         if (c != '"')
-           fatal_expected_char (infile, '"', c);
 
-         while (1)
-           {
-             c = getc (infile); /* Read the string  */
-             if (c == '\n')
-               read_rtx_lineno++;
-             if (c == '\\')
-               {
-                 c = getc (infile);    /* Read the string  */
-                 /* \; makes stuff for a C string constant containing
-                    newline and tab.  */
-                 if (c == ';')
-                   {
-                     obstack_grow (&rtl_obstack, "\\n\\t", 4);
-                     continue;
-                   }
-                 if (c == '\n')
-                   read_rtx_lineno++;
-               }
-             else if (c == '"')
-               break;
-
-             obstack_1grow (&rtl_obstack, c);
-           }
-
-         obstack_1grow (&rtl_obstack, 0);
-         stringbuf = (char *) obstack_finish (&rtl_obstack);
-
-         if (saw_paren)
-           {
-             c = read_skip_spaces (infile);
-             if (c != ')')
-               fatal_expected_char (infile, ')', c);
-           }
          XSTR (return_rtx, i) = stringbuf;
        }
        break;
@@ -1136,9 +1292,10 @@ rtl_check_failed_bounds (r, n, file, line, func)
     int line;
     const char *func;
 {
-  error ("RTL check: access of elt %d of `%s' with last elt %d",
-        n, GET_RTX_NAME (GET_CODE (r)), GET_RTX_LENGTH (GET_CODE (r))-1);
-  fancy_abort (file, line, func);
+  internal_error
+    ("RTL check: access of elt %d of `%s' with last elt %d in %s, at %s:%d",
+     n, GET_RTX_NAME (GET_CODE (r)), GET_RTX_LENGTH (GET_CODE (r)) - 1,
+     func, trim_filename (file), line);
 }
 
 void
@@ -1150,9 +1307,10 @@ rtl_check_failed_type1 (r, n, c1, file, line, func)
     int line;
     const char *func;
 {
-  error ("RTL check: expected elt %d type '%c', have '%c' (rtx %s)",
-        n, c1, GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE (r)));
-  fancy_abort (file, line, func);
+  internal_error
+    ("RTL check: expected elt %d type '%c', have '%c' (rtx %s) in %s, at %s:%d",
+     n, c1, GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE (r)),
+     func, trim_filename (file), line);
 }
 
 void
@@ -1165,10 +1323,10 @@ rtl_check_failed_type2 (r, n, c1, c2, file, line, func)
     int line;
     const char *func;
 {
-  error ("RTL check: expected elt %d type '%c' or '%c', have '%c' (rtx %s)",
-        n, c1, c2,
-        GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE(r)));
-  fancy_abort (file, line, func);
+  internal_error
+    ("RTL check: expected elt %d type '%c' or '%c', have '%c' (rtx %s) in %s, at %s:%d",
+     n, c1, c2, GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE (r)),
+     func, trim_filename (file), line);
 }
 
 void
@@ -1179,9 +1337,9 @@ rtl_check_failed_code1 (r, code, file, line, func)
     int line;
     const char *func;
 {
-  error ("RTL check: expected code `%s', have `%s'",
-        GET_RTX_NAME (code), GET_RTX_NAME (GET_CODE (r)));
-  fancy_abort (file, line, func);
+  internal_error ("RTL check: expected code `%s', have `%s' in %s, at %s:%d",
+                 GET_RTX_NAME (code), GET_RTX_NAME (GET_CODE (r)), func,
+                 trim_filename (file), line);
 }
 
 void
@@ -1192,10 +1350,10 @@ rtl_check_failed_code2 (r, code1, code2, file, line, func)
     int line;
     const char *func;
 {
-  error ("RTL check: expected code `%s' or `%s', have `%s'",
-        GET_RTX_NAME (code1), GET_RTX_NAME (code2),
-        GET_RTX_NAME (GET_CODE (r)));
-  fancy_abort (file, line, func);
+  internal_error
+    ("RTL check: expected code `%s' or `%s', have `%s' in %s, at %s:%d",
+     GET_RTX_NAME (code1), GET_RTX_NAME (code2), GET_RTX_NAME (GET_CODE (r)),
+     func, trim_filename (file), line);
 }
 
 /* XXX Maybe print the vector?  */
@@ -1207,8 +1365,8 @@ rtvec_check_failed_bounds (r, n, file, line, func)
     int line;
     const char *func;
 {
-  error ("RTL check: access of elt %d of vector with last elt %d",
-        n, GET_NUM_ELEM (r)-1);
-  fancy_abort (file, line, func);
+  internal_error
+    ("RTL check: access of elt %d of vector with last elt %d in %s, at %s:%d",
+     n, GET_NUM_ELEM (r) - 1, func, trim_filename (file), line);
 }
 #endif /* ENABLE_RTL_CHECKING */