/* 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.
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.
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).
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. */
"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:
/* 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. */
+ (( 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;
}
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,
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);
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);
}
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;
case PC:
case CC0:
return orig;
+ default:
+ break;
}
copy = rtx_alloc (code);
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);
}
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;
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 == '/')
{
dump_and_abort ('*', c, infile);
prevc = 0;
- while (c = getc (infile))
+ while ((c = getc (infile)) && c != EOF)
{
if (prevc == '*' && c == '/')
break;
*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
rtx return_rtx;
register int c;
int tmp_int;
+ HOST_WIDE_INT tmp_wide;
/* Linked list structure for making RTXs: */
struct rtx_list
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 != '[')
}
/* 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;
{
int saw_paren = 0;
register char *stringbuf;
- int stringbufsize;
c = read_skip_spaces (infile);
if (c == '(')
}
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)
{
}
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);
*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
}
#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;
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 */