OSDN Git Service

* config/linux.h (ASM_COMMENT_START): Remove from here,
[pf3gnuchains/gcc-fork.git] / gcc / rtl.c
index dc9e218..712a9c5 100644 (file)
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -1,5 +1,5 @@
 /* Allocate and read RTL for GNU C Compiler.
-   Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1991, 1994, 1997 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,19 +15,18 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 #include "config.h"
-#include <ctype.h>
-#include <stdio.h>
+#include "system.h"
 #include "rtl.h"
+#include "real.h"
 
 #include "obstack.h"
 #define        obstack_chunk_alloc     xmalloc
 #define        obstack_chunk_free      free
-extern int xmalloc ();
-extern void free ();
 
 /* Obstack used for allocating RTL objects.
    Between functions, this is the permanent_obstack.
@@ -36,8 +35,6 @@ extern void free ();
    During optimization and output, this is function_obstack.  */
 
 extern struct obstack *rtl_obstack;
-
-extern long ftell();
 \f
 /* Indexed by rtx code, gives number of operands for an rtx with that code.
    Does NOT include rtx header data (code and links).
@@ -121,11 +118,6 @@ enum machine_mode mode_wider_mode[(int) MAX_MACHINE_MODE] = {
 
 enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS];
 
-/* Commonly used modes.  */
-
-enum machine_mode byte_mode;   /* Mode whose width is BITS_PER_UNIT */
-enum machine_mode word_mode;   /* Mode whose width is BITS_PER_WORD */
-
 /* Indexed by rtx code, gives a sequence of operand-types for
    rtx's of that code.  The sequence is a C string in which
    each character describes one operand.  */
@@ -138,6 +130,8 @@ char *rtx_format[] = {
      "i" an integer
          prints the integer
      "n" like "i", but prints entries from `note_insn_name'
+     "w" an integer of width HOST_BITS_PER_WIDE_INT
+         prints the integer
      "s" a pointer to a string
          prints the string
      "S" like "s", but optional:
@@ -167,18 +161,27 @@ char rtx_class[] = {
 
 /* Names for kinds of NOTEs and REG_NOTEs.  */
 
-char *note_insn_name[] = { "NOTE_INSN_FUNCTION_BEG", "NOTE_INSN_DELETED",
+char *note_insn_name[] = { 0                    , "NOTE_INSN_DELETED",
                           "NOTE_INSN_BLOCK_BEG", "NOTE_INSN_BLOCK_END",
                           "NOTE_INSN_LOOP_BEG", "NOTE_INSN_LOOP_END",
                           "NOTE_INSN_FUNCTION_END", "NOTE_INSN_SETJMP",
-                          "NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP" };
+                          "NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP",
+                          "NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG",
+                          "NOTE_INSN_DELETED_LABEL", "NOTE_INSN_FUNCTION_BEG",
+                          "NOTE_INSN_EH_REGION_BEG", "NOTE_INSN_EH_REGION_END",
+                          "NOTE_REPEATED_LINE_NUMBER" };
 
 char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
                          "REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
                          "REG_NONNEG", "REG_NO_CONFLICT", "REG_UNUSED",
                          "REG_CC_SETTER", "REG_CC_USER", "REG_LABEL",
-                         "REG_DEP_ANTI", "REG_DEP_OUTPUT" };
+                         "REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_BR_PROB",
+                         "REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA",
+                         "REG_BR_PRED", "REG_EH_CONTEXT" };
 
+static void dump_and_abort     PROTO((int, int, FILE *));
+static void read_name          PROTO((char *, FILE *));
+\f
 /* Allocate an rtx vector of N elements.
    Store the length, and initialize all elements to zero.  */
 
@@ -194,9 +197,10 @@ rtvec_alloc (n)
                              + (( n - 1) * sizeof (rtunion)));
 
   /* clear out the vector */
-  PUT_NUM_ELEM(rt, n);
-  for (i=0; i < n; i++)
-    rt->elem[i].rtvec = NULL;  /* @@ not portable due to rtunion */
+  PUT_NUM_ELEM (rt, n);
+
+  for (i = 0; i < n; i++)
+    rt->elem[i].rtwint = 0;
 
   return rt;
 }
@@ -229,11 +233,27 @@ rtx_alloc (code)
   ob->next_free += length;
   ob->object_base = ob->next_free;
 
-  * (int *) rt = 0;
+  /* We want to clear everything up to the FLD array.  Normally, this is
+     one int, but we don't want to assume that and it isn't very portable
+     anyway; this is.  */
+
+  length = (sizeof (struct rtx_def) - sizeof (rtunion) - 1) / sizeof (int);
+  for (; length >= 0; length--)
+    ((int *) rt)[length] = 0;
+
   PUT_CODE (rt, code);
 
   return rt;
 }
+
+/* Free the rtx X and all RTL allocated since X.  */
+
+void
+rtx_free (x)
+     rtx x;
+{
+  obstack_free (rtl_obstack, x);
+}
 \f
 /* Create a new copy of an rtx.
    Recursively copies the operands of the rtx,
@@ -260,7 +280,27 @@ copy_rtx (orig)
     case CODE_LABEL:
     case PC:
     case CC0:
+    case SCRATCH:
+      /* SCRATCH must be shared because they represent distinct values.  */
+    case ADDRESSOF:
       return orig;
+
+    case CONST:
+      /* CONST can be shared if it contains a SYMBOL_REF.  If it contains
+        a LABEL_REF, it isn't sharable.  */
+      if (GET_CODE (XEXP (orig, 0)) == PLUS
+         && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
+         && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT)
+       return orig;
+      break;
+
+      /* A MEM with a constant address is not sharable.  The problem is that
+        the constant address may need to be reloaded.  If the mem is shared,
+        then reloading one copy of this mem will cause all copies to appear
+        to have been reloaded.  */
+
+    default:
+      break;
     }
 
   copy = rtx_alloc (code);
@@ -282,6 +322,11 @@ copy_rtx (orig)
            XEXP (copy, i) = copy_rtx (XEXP (orig, i));
          break;
 
+       case '0':
+       case 'u':
+         XEXP (copy, i) = XEXP (orig, i);
+         break;
+
        case 'E':
        case 'V':
          XVEC (copy, i) = XVEC (orig, i);
@@ -293,9 +338,21 @@ copy_rtx (orig)
            }
          break;
 
-       default:
+       case 'w':
+         XWINT (copy, i) = XWINT (orig, i);
+         break;
+
+       case 'i':
          XINT (copy, i) = XINT (orig, i);
          break;
+
+       case 's':
+       case 'S':
+         XSTR (copy, i) = XSTR (orig, i);
+         break;
+
+       default:
+         abort ();
        }
     }
   return copy;
@@ -330,6 +387,8 @@ copy_most_rtx (orig, may_share)
     case PC:
     case CC0:
       return orig;
+    default:
+      break;
     }
 
   copy = rtx_alloc (code);
@@ -351,6 +410,11 @@ copy_most_rtx (orig, may_share)
            XEXP (copy, i) = copy_most_rtx (XEXP (orig, i), may_share);
          break;
 
+       case '0':
+       case 'u':
+         XEXP (copy, i) = XEXP (orig, i);
+         break;
+
        case 'E':
        case 'V':
          XVEC (copy, i) = XVEC (orig, i);
@@ -363,9 +427,22 @@ copy_most_rtx (orig, may_share)
            }
          break;
 
-       default:
+       case 'w':
+         XWINT (copy, i) = XWINT (orig, i);
+         break;
+
+       case 'n':
+       case 'i':
          XINT (copy, i) = XINT (orig, i);
          break;
+
+       case 's':
+       case 'S':
+         XSTR (copy, i) = XSTR (orig, i);
+         break;
+
+       default:
+         abort ();
        }
     }
   return copy;
@@ -409,13 +486,14 @@ read_skip_spaces (infile)
      FILE *infile;
 {
   register int c;
-  while (c = getc (infile))
+  while ((c = getc (infile)))
     {
       if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
        ;
       else if (c == ';')
        {
-         while ((c = getc (infile)) && c != '\n') ;
+         while ((c = getc (infile)) && c != '\n' && c != EOF)
+           ;
        }
       else if (c == '/')
        {
@@ -425,7 +503,7 @@ read_skip_spaces (infile)
            dump_and_abort ('*', c, infile);
          
          prevc = 0;
-         while (c = getc (infile))
+         while ((c = getc (infile)) && c != EOF)
            {
              if (prevc == '*' && c == '/')
                break;
@@ -473,6 +551,43 @@ read_name (str, infile)
   *p = 0;
 }
 \f
+/* Provide a version of a function to read a long long if the system does
+   not provide one.  */
+#if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !defined(HAVE_ATOLL) && !defined(HAVE_ATOQ)
+HOST_WIDE_INT
+atoll(p)
+    const char *p;
+{
+  int neg = 0;
+  HOST_WIDE_INT tmp_wide;
+
+  while (ISSPACE(*p))
+    p++;
+  if (*p == '-')
+    neg = 1, p++;
+  else if (*p == '+')
+    p++;
+
+  tmp_wide = 0;
+  while (ISDIGIT(*p))
+    {
+      HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0');
+      if (new_wide < tmp_wide)
+       {
+         /* Return INT_MAX equiv on overflow.  */
+         tmp_wide = (~(unsigned HOST_WIDE_INT)0) >> 1;
+         break;
+       }
+      tmp_wide = new_wide;
+      p++;
+    }
+
+  if (neg)
+    tmp_wide = -tmp_wide;
+  return tmp_wide;
+}
+#endif
+
 /* 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
@@ -492,6 +607,7 @@ read_rtx (infile)
   rtx return_rtx;
   register int c;
   int tmp_int;
+  HOST_WIDE_INT tmp_wide;
 
   /* Linked list structure for making RTXs: */
   struct rtx_list
@@ -579,7 +695,7 @@ read_rtx (infile)
       case 'E':
        {
          register struct rtx_list *next_rtx, *rtx_list_link;
-         struct rtx_list *list_rtx;
+         struct rtx_list *list_rtx = NULL;
 
          c = read_skip_spaces (infile);
          if (c != '[')
@@ -604,8 +720,7 @@ read_rtx (infile)
            }
          /* get vector length and allocate it */
          XVEC (return_rtx, i) = (list_counter
-                                 ? rtvec_alloc (list_counter)
-                                 : (struct rtvec_def *) NULL);
+                                 ? rtvec_alloc (list_counter) : NULL_RTVEC);
          if (list_counter > 0)
            {
              next_rtx = list_rtx;
@@ -632,7 +747,6 @@ read_rtx (infile)
        {
          int saw_paren = 0;
          register char *stringbuf;
-         int stringbufsize;
 
          c = read_skip_spaces (infile);
          if (c == '(')
@@ -642,36 +756,29 @@ read_rtx (infile)
            }
          if (c != '"')
            dump_and_abort ('"', c, infile);
-         j = 0;
-         stringbufsize = 10;
-         stringbuf = (char *) xmalloc (stringbufsize + 1);
 
          while (1)
            {
-             if (j >= stringbufsize - 4)
-               {
-                 stringbufsize *= 2;
-                 stringbuf = (char *) xrealloc (stringbuf, stringbufsize + 1);
-               }
-             stringbuf[j] = getc (infile); /* Read the string  */
-             if (stringbuf[j] == '\\')
+             c = getc (infile); /* Read the string  */
+             if (c == '\\')
                {
-                 stringbuf[j] = getc (infile); /* Read the string  */
+                 c = getc (infile);    /* Read the string  */
                  /* \; makes stuff for a C string constant containing
                     newline and tab.  */
-                 if (stringbuf[j] == ';')
+                 if (c == ';')
                    {
-                     strcpy (&stringbuf[j], "\\n\\t");
-                     j += 3;
+                     obstack_grow (rtl_obstack, "\\n\\t", 4);
+                     continue;
                    }
                }
-             else if (stringbuf[j] == '"')
+             else if (c == '"')
                break;
-             j++;
+
+             obstack_1grow (rtl_obstack, c);
            }
 
-         stringbuf[j] = 0;     /* NUL terminate the string  */
-         stringbuf = (char *) xrealloc (stringbuf, j + 1);
+         obstack_1grow (rtl_obstack, 0);
+         stringbuf = (char *) obstack_finish (rtl_obstack);
 
          if (saw_paren)
            {
@@ -683,6 +790,26 @@ read_rtx (infile)
        }
        break;
 
+      case 'w':
+       read_name (tmp_char, infile);
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+       tmp_wide = atoi (tmp_char);
+#else
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+       tmp_wide = atol (tmp_char);
+#else
+       /* Prefer atoll over atoq, since the former is in the ISO C9X draft. 
+          But prefer not to use our hand-rolled function above either.  */
+#if defined(HAVE_ATOLL) || !defined(HAVE_ATOQ)
+       tmp_wide = atoll (tmp_char);
+#else
+       tmp_wide = atoq (tmp_char);
+#endif
+#endif
+#endif
+       XWINT (return_rtx, i) = tmp_wide;
+       break;
+
       case 'i':
       case 'n':
        read_name (tmp_char, infile);
@@ -734,9 +861,10 @@ init_rtl ()
       *s++ = 'e';
       *s++ = '0';
       /* Set the GET_RTX_FORMAT of CONST_DOUBLE to a string
-        of as many `i's as we now have elements.  */
-      for (i = 0; i < rtx_length[(int) CONST_DOUBLE]; i++)
-       *s++ = 'i';
+        of as many `w's as we now have elements.  Subtract two from
+        the size to account for the 'e' and the '0'.  */
+      for (i = 2; i < rtx_length[(int) CONST_DOUBLE]; i++)
+       *s++ = 'w';
       *s++ = 0;
     }
 #endif
@@ -752,8 +880,7 @@ init_rtl ()
     }
 #endif
 
-  /* Find the narrowest mode for each class and compute the word and byte
-     modes.  */
+  /* Find the narrowest mode for each class.  */
 
   for (i = 0; i < (int) MAX_MODE_CLASS; i++)
     min_class_size[i] = 1000;
@@ -766,23 +893,5 @@ init_rtl ()
          class_narrowest_mode[(int) GET_MODE_CLASS (mode)] = mode;
          min_class_size[(int) GET_MODE_CLASS (mode)] = GET_MODE_SIZE (mode);
        }
-      if (GET_MODE_CLASS (mode) == MODE_INT
-         && GET_MODE_BITSIZE (mode) == BITS_PER_UNIT)
-       byte_mode = mode;
-
-      if (GET_MODE_CLASS (mode) == MODE_INT
-         && GET_MODE_BITSIZE (mode) == BITS_PER_WORD)
-       word_mode = mode;
     }
 }
-\f
-#ifdef memset
-gcc_memset (dest, value, len)
-     char *dest;
-     int value;
-     int len;
-{
-  while (len-- > 0)
-    *dest++ = value;
-}
-#endif /* memset */