summaryrefslogtreecommitdiff
path: root/gcc/rtl.c
diff options
context:
space:
mode:
authorzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>2001-06-28 21:50:09 +0000
committerzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>2001-06-28 21:50:09 +0000
commit875d87406e33f9234d87a19e92ab9ac383f89661 (patch)
treeac4e7f001b87da3b312391bda96de6043b090057 /gcc/rtl.c
parent49f45d837e1b1356a0d158191677ac62023314a1 (diff)
downloadgcc-875d87406e33f9234d87a19e92ab9ac383f89661.tar.gz
* config/i386/i386.md: Global update to use new string syntax
where it will improve readability. Warning fixes: (*truncdfsf2_2): Abort if which_alternative is not 0 or 1. (*adddi_1_rex64, *adddi_2_rex64, *adddi_3_rex64, *adddi_4_rex64, *adddi_5_rex64): Cast 1 to unsigned int. * read-rtl.c: Syntactic sugar for C embedded in strings in machine descriptions. (read_string): Break inner loop into separate function. Takes an int. Dispatch to read_quoted_string or read_braced_string as appropriate. Automatically insert a leading star on braced strings if STAR_IF_BRACED is true. (read_quoted_string, read_braced_string): New functions. * doc/rtl.texi, doc/md.texi: Document new syntax. Update examples to match. * rtl.c: Split RTL reader (read_rtx, read_skip_spaces, traverse_md_constants, fatal_with_file_and_line, fatal_expected_char, read_name, read_string, def_hash, def_name_eq_p, read_constants, and related data) to its own file. Weed out now-unnecessary #includes. * read-rtl.c: New file. * Makefile.in (HOST_RTL): Add read-rtl.o. (read-rtl.o): New rule. (rtl.o, $(HOST_PREFIX_1)rtl.o): Update dependencies. * doc/gcc.texi (Passes): Talk briefly about the support library used by genfoo. * doc/rtl.texi (Reading RTL): read_rtx is not available in the compiler itself. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@43646 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/rtl.c')
-rw-r--r--gcc/rtl.c616
1 files changed, 2 insertions, 614 deletions
diff --git a/gcc/rtl.c b/gcc/rtl.c
index 0fad1369782..0c84d752e3e 100644
--- 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, 1994, 1997, 1998, 1999, 2000
+/* RTL utility routines.
+ Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,19 +19,11 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
#include "config.h"
#include "system.h"
#include "rtl.h"
#include "real.h"
-#include "bitmap.h"
#include "ggc.h"
-#include "obstack.h"
-#include "toplev.h"
-#include "hashtab.h"
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
/* Calculate the format for CONST_DOUBLE. This depends on the relative
@@ -292,17 +284,6 @@ const char * const reg_note_name[] =
"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));
-
/* Allocate an rtx vector of N elements.
Store the length, and initialize all elements to zero. */
@@ -690,599 +671,6 @@ rtx_equal_p (x, y)
return 1;
}
-/* Subroutines of read_rtx. */
-
-/* The current line number for the file. */
-int read_rtx_lineno = 1;
-
-/* The filename for aborting with file and line. */
-const char *read_rtx_filename = "<unknown>";
-
-static void
-fatal_with_file_and_line VPARAMS ((FILE *infile, const char *msg, ...))
-{
-#ifndef ANSI_PROTOTYPES
- FILE *infile;
- const char *msg;
-#endif
- va_list ap;
- char context[64];
- size_t i;
- int c;
-
- VA_START (ap, msg);
-
-#ifndef ANSI_PROTOTYPES
- infile = va_arg (ap, FILE *);
- msg = va_arg (ap, const char *);
-#endif
-
- fprintf (stderr, "%s:%d: ", read_rtx_filename, read_rtx_lineno);
- vfprintf (stderr, msg, ap);
- putc ('\n', stderr);
-
- /* Gather some following context. */
- for (i = 0; i < sizeof(context)-1; ++i)
- {
- c = getc (infile);
- if (c == EOF)
- break;
- if (c == '\r' || c == '\n')
- break;
- context[i] = c;
- }
- context[i] = '\0';
-
- fprintf (stderr, "%s:%d: following context is `%s'\n",
- read_rtx_filename, read_rtx_lineno, context);
-
- va_end (ap);
- exit (1);
-}
-
-/* Dump code after printing a message. Used when read_rtx finds
- invalid data. */
-
-static void
-fatal_expected_char (infile, expected_c, actual_c)
- FILE *infile;
- int expected_c, actual_c;
-{
- fatal_with_file_and_line (infile, "expected character `%c', found `%c'",
- expected_c, actual_c);
-}
-
-/* Read chars from INFILE until a non-whitespace char
- and return that. Comments, both Lisp style and C style,
- are treated as whitespace.
- Tools such as genflags use this function. */
-
-int
-read_skip_spaces (infile)
- FILE *infile;
-{
- register int c;
- while (1)
- {
- c = getc (infile);
- switch (c)
- {
- case '\n':
- read_rtx_lineno++;
- break;
-
- case ' ': case '\t': case '\f': case '\r':
- break;
-
- case ';':
- do
- c = getc (infile);
- while (c != '\n' && c != EOF);
- read_rtx_lineno++;
- break;
-
- case '/':
- {
- register int prevc;
- c = getc (infile);
- if (c != '*')
- fatal_expected_char (infile, '*', c);
-
- prevc = 0;
- while ((c = getc (infile)) && c != EOF)
- {
- if (c == '\n')
- read_rtx_lineno++;
- else if (prevc == '*' && c == '/')
- break;
- prevc = c;
- }
- }
- break;
-
- default:
- return c;
- }
- }
-}
-
-/* Read an rtx code name into the buffer STR[].
- It is terminated by any of the punctuation chars of rtx printed syntax. */
-
-static void
-read_name (str, infile)
- char *str;
- FILE *infile;
-{
- register char *p;
- register int c;
-
- c = read_skip_spaces(infile);
-
- p = str;
- while (1)
- {
- if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
- break;
- if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
- || c == '(' || c == '[')
- {
- ungetc (c, infile);
- break;
- }
- *p++ = c;
- c = getc (infile);
- }
- if (p == str)
- fatal_with_file_and_line (infile, "missing name or number");
- if (c == '\n')
- 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;
-}
-
-/* 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
-
-/* 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
- the utilities gen*.c that construct C code from machine descriptions. */
-
-rtx
-read_rtx (infile)
- FILE *infile;
-{
- register int i, j;
- RTX_CODE tmp_code;
- register const char *format_ptr;
- /* tmp_char is a buffer used for reading decimal integers
- and names of rtx types and machine modes.
- Therefore, 256 must be enough. */
- char tmp_char[256];
- rtx return_rtx;
- register int c;
- int tmp_int;
- HOST_WIDE_INT tmp_wide;
-
- /* Obstack used for allocating RTL objects. */
- static struct obstack rtl_obstack;
- static int initialized;
-
- /* Linked list structure for making RTXs: */
- struct rtx_list
- {
- struct rtx_list *next;
- rtx value; /* Value of this node. */
- };
-
- if (!initialized) {
- _obstack_begin (&rtl_obstack,0, 0,
- (void *(*) PARAMS ((long))) xmalloc,
- (void (*) PARAMS ((void *))) free);
- initialized = 1;
- }
-
-again:
- c = read_skip_spaces (infile); /* Should be open paren. */
- if (c != '(')
- fatal_expected_char (infile, '(', c);
-
- read_name (tmp_char, 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)))
- {
- tmp_code = (RTX_CODE) i; /* get value for name */
- break;
- }
-
- if (tmp_code == UNKNOWN)
- fatal_with_file_and_line (infile, "unknown rtx code `%s'", tmp_char);
-
- /* (NIL) stands for an expression that isn't there. */
- if (tmp_code == NIL)
- {
- /* Discard the closeparen. */
- while ((c = getc (infile)) && c != ')')
- ;
-
- return 0;
- }
-
- /* If we end up with an insn expression then we free this space below. */
- return_rtx = rtx_alloc (tmp_code);
- format_ptr = GET_RTX_FORMAT (GET_CODE (return_rtx));
-
- /* If what follows is `: mode ', read it and
- store the mode in the rtx. */
-
- i = read_skip_spaces (infile);
- if (i == ':')
- {
- read_name (tmp_char, infile);
- for (j = 0; j < NUM_MACHINE_MODES; j++)
- if (! strcmp (GET_MODE_NAME (j), tmp_char))
- break;
-
- if (j == MAX_MACHINE_MODE)
- fatal_with_file_and_line (infile, "unknown mode `%s'", tmp_char);
-
- PUT_MODE (return_rtx, (enum machine_mode) j);
- }
- else
- ungetc (i, infile);
-
- for (i = 0; i < GET_RTX_LENGTH (GET_CODE (return_rtx)); i++)
- switch (*format_ptr++)
- {
- /* 0 means a field for internal use only.
- Don't expect it to be present in the input. */
- case '0':
- break;
-
- case 'e':
- case 'u':
- XEXP (return_rtx, i) = read_rtx (infile);
- break;
-
- case 'V':
- /* 'V' is an optional vector: if a closeparen follows,
- just store NULL for this element. */
- c = read_skip_spaces (infile);
- ungetc (c, infile);
- if (c == ')')
- {
- XVEC (return_rtx, i) = 0;
- break;
- }
- /* Now process the vector. */
-
- case 'E':
- {
- /* 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 */
- obstack_init (&vector_stack);
- while ((c = read_skip_spaces (infile)) && c != ']')
- {
- ungetc (c, infile);
- list_counter++;
- obstack_ptr_grow (&vector_stack, (PTR) read_rtx (infile));
- }
- if (list_counter > 0)
- {
- 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;
-
- case 'S':
- /* 'S' is an optional string: if a closeparen follows,
- just store NULL for this element. */
- c = read_skip_spaces (infile);
- ungetc (c, infile);
- if (c == ')')
- {
- XSTR (return_rtx, i) = 0;
- break;
- }
-
- case 's':
- {
- 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))
- {
- 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);
- }
-
- XSTR (return_rtx, i) = stringbuf;
- }
- 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 C99 standard.
- 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);
- tmp_int = atoi (tmp_char);
- XINT (return_rtx, i) = tmp_int;
- break;
-
- default:
- fprintf (stderr,
- "switch format wrong in rtl.read_rtx(). format was: %c.\n",
- format_ptr[-1]);
- fprintf (stderr, "\tfile position: %ld\n", ftell (infile));
- abort ();
- }
-
- c = read_skip_spaces (infile);
- if (c != ')')
- fatal_expected_char (infile, ')', c);
-
- return return_rtx;
-}
-
#if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007)
void
rtl_check_failed_bounds (r, n, file, line, func)