diff options
author | zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-06-28 21:50:09 +0000 |
---|---|---|
committer | zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-06-28 21:50:09 +0000 |
commit | 875d87406e33f9234d87a19e92ab9ac383f89661 (patch) | |
tree | ac4e7f001b87da3b312391bda96de6043b090057 /gcc/rtl.c | |
parent | 49f45d837e1b1356a0d158191677ac62023314a1 (diff) | |
download | gcc-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.c | 616 |
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) |