X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fread-rtl.c;h=1402c5468371c0a90fbf63b59c65bca6bd2dbade;hb=a484fc356e716397e5545f3c48005268e28b632d;hp=89a7c9722839d39abad9fcd896811a91e5c78475;hpb=e08825b460643d800cd534d88786994c7d06e639;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c index 89a7c972283..1402c546837 100644 --- a/gcc/read-rtl.c +++ b/gcc/read-rtl.c @@ -1,13 +1,13 @@ /* RTL reader for GCC. Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005 + 2003, 2004, 2005, 2007, 2008, 2010 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -16,13 +16,12 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ #include "bconfig.h" -/* Disable rtl checking; it conflicts with the macro handling. */ +/* Disable rtl checking; it conflicts with the iterator handling. */ #undef ENABLE_RTL_CHECKING #include "system.h" @@ -31,10 +30,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "rtl.h" #include "obstack.h" #include "hashtab.h" +#include "read-md.h" #include "gensupport.h" -static htab_t md_constants; - /* One element in a singly-linked list of (integer, string) pairs. */ struct map_value { struct map_value *next; @@ -42,17 +40,17 @@ struct map_value { const char *string; }; -/* Maps a macro or attribute name to a list of (integer, string) pairs. +/* Maps an iterator or attribute name to a list of (integer, string) pairs. The integers are mode or code values; the strings are either C conditions or attribute values. */ struct mapping { - /* The name of the macro or attribute. */ + /* The name of the iterator or attribute. */ const char *name; - /* The group (modes or codes) to which the macro or attribute belongs. */ - struct macro_group *group; + /* The group (modes or codes) to which the iterator or attribute belongs. */ + struct iterator_group *group; - /* Gives a unique number to the attribute or macro. Numbers are + /* Gives a unique number to the attribute or iterator. Numbers are allocated consecutively, starting at 0. */ int index; @@ -60,173 +58,79 @@ struct mapping { struct map_value *values; }; -/* A structure for abstracting the common parts of code and mode macros. */ -struct macro_group { - /* Tables of "mapping" structures, one for attributes and one for macros. */ - htab_t attrs, macros; +/* A structure for abstracting the common parts of code and mode iterators. */ +struct iterator_group { + /* Tables of "mapping" structures, one for attributes and one for iterators. */ + htab_t attrs, iterators; /* The number of "real" modes or codes (and by extension, the first - number available for use as a macro placeholder). */ + number available for use as an iterator placeholder). */ int num_builtins; /* Treat the given string as the name of a standard mode or code and - return its integer value. Use the given file for error reporting. */ - int (*find_builtin) (const char *, FILE *); + return its integer value. */ + int (*find_builtin) (const char *); /* Return true if the given rtx uses the given mode or code. */ - bool (*uses_macro_p) (rtx, int); + bool (*uses_iterator_p) (rtx, int); /* Make the given rtx use the given mode or code. */ - void (*apply_macro) (rtx, int); -}; - -/* Associates PTR (which can be a string, etc.) with the file location - specified by FILENAME and LINENO. */ -struct ptr_loc { - const void *ptr; - const char *filename; - int lineno; + void (*apply_iterator) (rtx, int); }; -/* A structure used to pass data from read_rtx to apply_macro_traverse +/* A structure used to pass data from read_rtx to apply_iterator_traverse via htab_traverse. */ -struct macro_traverse_data { +struct iterator_traverse_data { /* Instruction queue. */ rtx queue; /* Attributes seen for modes. */ struct map_value *mode_maps; - /* Input file. */ - FILE *infile; /* The last unknown attribute used as a mode. */ const char *unknown_mode_attr; }; -/* If CODE is the number of a code macro, return a real rtx code that +/* If CODE is the number of a code iterator, return a real rtx code that has the same format. Return CODE otherwise. */ #define BELLWETHER_CODE(CODE) \ ((CODE) < NUM_RTX_CODE ? CODE : bellwether_codes[CODE - NUM_RTX_CODE]) -static void fatal_with_file_and_line (FILE *, const char *, ...) - ATTRIBUTE_PRINTF_2 ATTRIBUTE_NORETURN; -static void fatal_expected_char (FILE *, int, int) ATTRIBUTE_NORETURN; -static int find_mode (const char *, FILE *); -static bool uses_mode_macro_p (rtx, int); -static void apply_mode_macro (rtx, int); -static int find_code (const char *, FILE *); -static bool uses_code_macro_p (rtx, int); -static void apply_code_macro (rtx, int); -static const char *apply_macro_to_string (const char *, struct mapping *, int); -static rtx apply_macro_to_rtx (rtx, struct mapping *, int, - struct map_value *, FILE *, const char **); -static bool uses_macro_p (rtx, struct mapping *); +static int find_mode (const char *); +static bool uses_mode_iterator_p (rtx, int); +static void apply_mode_iterator (rtx, int); +static int find_code (const char *); +static bool uses_code_iterator_p (rtx, int); +static void apply_code_iterator (rtx, int); +static const char *apply_iterator_to_string (const char *, struct mapping *, int); +static rtx apply_iterator_to_rtx (rtx, struct mapping *, int, + struct map_value *, const char **); +static bool uses_iterator_p (rtx, struct mapping *); static const char *add_condition_to_string (const char *, const char *); static void add_condition_to_rtx (rtx, const char *); -static int apply_macro_traverse (void **, void *); -static struct mapping *add_mapping (struct macro_group *, htab_t t, - const char *, FILE *); +static int apply_iterator_traverse (void **, void *); +static struct mapping *add_mapping (struct iterator_group *, htab_t t, + const char *); static struct map_value **add_map_value (struct map_value **, int, const char *); -static void initialize_macros (void); -static void read_name (char *, FILE *); -static hashval_t leading_ptr_hash (const void *); -static int leading_ptr_eq_p (const void *, const void *); -static void set_rtx_ptr_loc (const void *, const char *, int); -static const struct ptr_loc *get_rtx_ptr_loc (const void *); -static char *read_string (FILE *, int); -static char *read_quoted_string (FILE *); -static char *read_braced_string (FILE *); -static void read_escape (FILE *); -static hashval_t def_hash (const void *); -static int def_name_eq_p (const void *, const void *); -static void read_constants (FILE *infile, char *tmp_char); -static void read_conditions (FILE *infile, char *tmp_char); -static void validate_const_int (FILE *, const char *); -static int find_macro (struct macro_group *, const char *, FILE *); -static struct mapping *read_mapping (struct macro_group *, htab_t, FILE *); -static void check_code_macro (struct mapping *, FILE *); -static rtx read_rtx_1 (FILE *, struct map_value **); -static rtx read_rtx_variadic (FILE *, struct map_value **, rtx); - -/* The mode and code macro structures. */ -static struct macro_group modes, codes; +static void initialize_iterators (void); +static void read_conditions (void); +static void validate_const_int (const char *); +static int find_iterator (struct iterator_group *, const char *); +static struct mapping *read_mapping (struct iterator_group *, htab_t); +static void check_code_iterator (struct mapping *); +static rtx read_rtx_code (const char *, struct map_value **); +static rtx read_nested_rtx (struct map_value **); +static rtx read_rtx_variadic (struct map_value **, rtx); + +/* The mode and code iterator structures. */ +static struct iterator_group modes, codes; /* Index I is the value of BELLWETHER_CODE (I + NUM_RTX_CODE). */ static enum rtx_code *bellwether_codes; -/* Obstack used for allocating RTL strings. */ -static struct obstack string_obstack; - -/* A table of ptr_locs, hashed on the PTR field. */ -static htab_t ptr_locs; - -/* An obstack for the above. Plain xmalloc is a bit heavyweight for a - small structure like ptr_loc. */ -static struct obstack ptr_loc_obstack; - -/* A hash table of triples (A, B, C), where each of A, B and C is a condition - and A is equivalent to "B && C". This is used to keep track of the source - of conditions that are made up of separate rtx strings (such as the split - condition of a define_insn_and_split). */ -static htab_t joined_conditions; - -/* An obstack for allocating joined_conditions entries. */ -static struct obstack joined_conditions_obstack; - -/* Subroutines of read_rtx. */ - -/* The current line number for the file. */ -int read_rtx_lineno = 1; - -/* The filename for error reporting. */ -const char *read_rtx_filename = ""; - -static void -fatal_with_file_and_line (FILE *infile, const char *msg, ...) -{ - char context[64]; - size_t i; - int c; - va_list ap; - - va_start (ap, msg); - - 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 (FILE *infile, int expected_c, int actual_c) -{ - fatal_with_file_and_line (infile, "expected character `%c', found `%c'", - expected_c, actual_c); -} - -/* Implementations of the macro_group callbacks for modes. */ +/* Implementations of the iterator_group callbacks for modes. */ static int -find_mode (const char *name, FILE *infile) +find_mode (const char *name) { int i; @@ -234,25 +138,25 @@ find_mode (const char *name, FILE *infile) if (strcmp (GET_MODE_NAME (i), name) == 0) return i; - fatal_with_file_and_line (infile, "unknown mode `%s'", name); + fatal_with_file_and_line ("unknown mode `%s'", name); } static bool -uses_mode_macro_p (rtx x, int mode) +uses_mode_iterator_p (rtx x, int mode) { return (int) GET_MODE (x) == mode; } static void -apply_mode_macro (rtx x, int mode) +apply_mode_iterator (rtx x, int mode) { PUT_MODE (x, (enum machine_mode) mode); } -/* Implementations of the macro_group callbacks for codes. */ +/* Implementations of the iterator_group callbacks for codes. */ static int -find_code (const char *name, FILE *infile) +find_code (const char *name) { int i; @@ -260,46 +164,46 @@ find_code (const char *name, FILE *infile) if (strcmp (GET_RTX_NAME (i), name) == 0) return i; - fatal_with_file_and_line (infile, "unknown rtx code `%s'", name); + fatal_with_file_and_line ("unknown rtx code `%s'", name); } static bool -uses_code_macro_p (rtx x, int code) +uses_code_iterator_p (rtx x, int code) { return (int) GET_CODE (x) == code; } static void -apply_code_macro (rtx x, int code) +apply_code_iterator (rtx x, int code) { PUT_CODE (x, (enum rtx_code) code); } /* Map a code or mode attribute string P to the underlying string for - MACRO and VALUE. */ + ITERATOR and VALUE. */ static struct map_value * -map_attr_string (const char *p, struct mapping *macro, int value) +map_attr_string (const char *p, struct mapping *iterator, int value) { const char *attr; struct mapping *m; struct map_value *v; - /* If there's a "macro:" prefix, check whether the macro name matches. + /* If there's a "iterator:" prefix, check whether the iterator name matches. Set ATTR to the start of the attribute name. */ attr = strchr (p, ':'); if (attr == 0) attr = p; else { - if (strncmp (p, macro->name, attr - p) != 0 - || macro->name[attr - p] != 0) + if (strncmp (p, iterator->name, attr - p) != 0 + || iterator->name[attr - p] != 0) return 0; attr++; } /* Find the attribute specification. */ - m = (struct mapping *) htab_find (macro->group->attrs, &attr); + m = (struct mapping *) htab_find (iterator->group->attrs, &attr); if (m == 0) return 0; @@ -313,7 +217,7 @@ map_attr_string (const char *p, struct mapping *macro, int value) /* Given an attribute string used as a machine mode, return an index to store in the machine mode to be translated by - apply_macro_to_rtx. */ + apply_iterator_to_rtx. */ static unsigned int mode_attr_index (struct map_value **mode_maps, const char *string) @@ -333,27 +237,26 @@ mode_attr_index (struct map_value **mode_maps, const char *string) *mode_maps = mv; /* We return a code which we can map back into this string: the - number of machine modes + the number of mode macros + the index + number of machine modes + the number of mode iterators + the index we just used. */ - return MAX_MACHINE_MODE + htab_elements (modes.macros) + mv->number; + return MAX_MACHINE_MODE + htab_elements (modes.iterators) + mv->number; } /* Apply MODE_MAPS to the top level of X, expanding cases where an - attribute is used for a mode. MACRO is the current macro we are + attribute is used for a mode. ITERATOR is the current iterator we are expanding, and VALUE is the value to which we are expanding it. - INFILE is used for error messages. This sets *UNKNOWN to true if - we find a mode attribute which has not yet been defined, and does - not change it otherwise. */ + This sets *UNKNOWN to true if we find a mode attribute which has not + yet been defined, and does not change it otherwise. */ static void -apply_mode_maps (rtx x, struct map_value *mode_maps, struct mapping *macro, - int value, FILE *infile, const char **unknown) +apply_mode_maps (rtx x, struct map_value *mode_maps, struct mapping *iterator, + int value, const char **unknown) { unsigned int offset; int indx; struct map_value *pm; - offset = MAX_MACHINE_MODE + htab_elements (modes.macros); + offset = MAX_MACHINE_MODE + htab_elements (modes.iterators); if (GET_MODE (x) < offset) return; @@ -364,9 +267,9 @@ apply_mode_maps (rtx x, struct map_value *mode_maps, struct mapping *macro, { struct map_value *v; - v = map_attr_string (pm->string, macro, value); + v = map_attr_string (pm->string, iterator, value); if (v) - PUT_MODE (x, (enum machine_mode) find_mode (v->string, infile)); + PUT_MODE (x, (enum machine_mode) find_mode (v->string)); else *unknown = pm->string; return; @@ -374,12 +277,12 @@ apply_mode_maps (rtx x, struct map_value *mode_maps, struct mapping *macro, } } -/* Given that MACRO is being expanded as VALUE, apply the appropriate +/* Given that ITERATOR is being expanded as VALUE, apply the appropriate string substitutions to STRING. Return the new string if any changes were needed, otherwise return STRING itself. */ static const char * -apply_macro_to_string (const char *string, struct mapping *macro, int value) +apply_iterator_to_string (const char *string, struct mapping *iterator, int value) { char *base, *copy, *p, *start, *end; struct map_value *v; @@ -393,7 +296,7 @@ apply_macro_to_string (const char *string, struct mapping *macro, int value) p = start + 1; *end = 0; - v = map_attr_string (p, macro, value); + v = map_attr_string (p, iterator, value); *end = '>'; if (v == 0) continue; @@ -408,24 +311,23 @@ apply_macro_to_string (const char *string, struct mapping *macro, int value) { obstack_grow (&string_obstack, base, strlen (base) + 1); copy = XOBFINISH (&string_obstack, char *); - copy_rtx_ptr_loc (copy, string); + copy_md_ptr_loc (copy, string); return copy; } return string; } -/* Return a copy of ORIGINAL in which all uses of MACRO have been +/* Return a copy of ORIGINAL in which all uses of ITERATOR have been replaced by VALUE. MODE_MAPS holds information about attribute - strings used for modes. INFILE is used for error messages. This - sets *UNKNOWN_MODE_ATTR to the value of an unknown mode attribute, - and does not change it otherwise. */ + strings used for modes. This sets *UNKNOWN_MODE_ATTR to the value of + an unknown mode attribute, and does not change it otherwise. */ static rtx -apply_macro_to_rtx (rtx original, struct mapping *macro, int value, - struct map_value *mode_maps, FILE *infile, - const char **unknown_mode_attr) +apply_iterator_to_rtx (rtx original, struct mapping *iterator, int value, + struct map_value *mode_maps, + const char **unknown_mode_attr) { - struct macro_group *group; + struct iterator_group *group; const char *format_ptr; int i, j; rtx x; @@ -437,15 +339,15 @@ apply_macro_to_rtx (rtx original, struct mapping *macro, int value, /* Create a shallow copy of ORIGINAL. */ bellwether_code = BELLWETHER_CODE (GET_CODE (original)); x = rtx_alloc (bellwether_code); - memcpy (x, original, RTX_SIZE (bellwether_code)); + memcpy (x, original, RTX_CODE_SIZE (bellwether_code)); /* Change the mode or code itself. */ - group = macro->group; - if (group->uses_macro_p (x, macro->index + group->num_builtins)) - group->apply_macro (x, value); + group = iterator->group; + if (group->uses_iterator_p (x, iterator->index + group->num_builtins)) + group->apply_iterator (x, value); if (mode_maps) - apply_mode_maps (x, mode_maps, macro, value, infile, unknown_mode_attr); + apply_mode_maps (x, mode_maps, iterator, value, unknown_mode_attr); /* Change each string and recursively change each rtx. */ format_ptr = GET_RTX_FORMAT (bellwether_code); @@ -453,18 +355,17 @@ apply_macro_to_rtx (rtx original, struct mapping *macro, int value, switch (format_ptr[i]) { case 'T': - XTMPL (x, i) = apply_macro_to_string (XTMPL (x, i), macro, value); + XTMPL (x, i) = apply_iterator_to_string (XTMPL (x, i), iterator, value); break; case 'S': case 's': - XSTR (x, i) = apply_macro_to_string (XSTR (x, i), macro, value); + XSTR (x, i) = apply_iterator_to_string (XSTR (x, i), iterator, value); break; case 'e': - XEXP (x, i) = apply_macro_to_rtx (XEXP (x, i), macro, value, - mode_maps, infile, - unknown_mode_attr); + XEXP (x, i) = apply_iterator_to_rtx (XEXP (x, i), iterator, value, + mode_maps, unknown_mode_attr); break; case 'V': @@ -473,10 +374,9 @@ apply_macro_to_rtx (rtx original, struct mapping *macro, int value, { XVEC (x, i) = rtvec_alloc (XVECLEN (original, i)); for (j = 0; j < XVECLEN (x, i); j++) - XVECEXP (x, i, j) = apply_macro_to_rtx (XVECEXP (original, i, j), - macro, value, mode_maps, - infile, - unknown_mode_attr); + XVECEXP (x, i, j) = apply_iterator_to_rtx (XVECEXP (original, i, j), + iterator, value, mode_maps, + unknown_mode_attr); } break; @@ -486,20 +386,20 @@ apply_macro_to_rtx (rtx original, struct mapping *macro, int value, return x; } -/* Return true if X (or some subexpression of X) uses macro MACRO. */ +/* Return true if X (or some subexpression of X) uses iterator ITERATOR. */ static bool -uses_macro_p (rtx x, struct mapping *macro) +uses_iterator_p (rtx x, struct mapping *iterator) { - struct macro_group *group; + struct iterator_group *group; const char *format_ptr; int i, j; if (x == 0) return false; - group = macro->group; - if (group->uses_macro_p (x, macro->index + group->num_builtins)) + group = iterator->group; + if (group->uses_iterator_p (x, iterator->index + group->num_builtins)) return true; format_ptr = GET_RTX_FORMAT (BELLWETHER_CODE (GET_CODE (x))); @@ -507,7 +407,7 @@ uses_macro_p (rtx x, struct mapping *macro) switch (format_ptr[i]) { case 'e': - if (uses_macro_p (XEXP (x, i), macro)) + if (uses_iterator_p (XEXP (x, i), iterator)) return true; break; @@ -515,7 +415,7 @@ uses_macro_p (rtx x, struct mapping *macro) case 'E': if (XVEC (x, i)) for (j = 0; j < XVECLEN (x, i); j++) - if (uses_macro_p (XVECEXP (x, i, j), macro)) + if (uses_iterator_p (XVECEXP (x, i, j), iterator)) return true; break; @@ -567,37 +467,37 @@ add_condition_to_rtx (rtx x, const char *extra) } /* A htab_traverse callback. Search the EXPR_LIST given by DATA - for rtxes that use the macro in *SLOT. Replace each such rtx + for rtxes that use the iterator in *SLOT. Replace each such rtx with a list of expansions. */ static int -apply_macro_traverse (void **slot, void *data) +apply_iterator_traverse (void **slot, void *data) { - struct macro_traverse_data *mtd = (struct macro_traverse_data *) data; - struct mapping *macro; + struct iterator_traverse_data *mtd = (struct iterator_traverse_data *) data; + struct mapping *iterator; struct map_value *v; rtx elem, new_elem, original, x; - macro = (struct mapping *) *slot; + iterator = (struct mapping *) *slot; for (elem = mtd->queue; elem != 0; elem = XEXP (elem, 1)) - if (uses_macro_p (XEXP (elem, 0), macro)) + if (uses_iterator_p (XEXP (elem, 0), iterator)) { - /* For each macro we expand, we set UNKNOWN_MODE_ATTR to NULL. - If apply_macro_rtx finds an unknown attribute for a mode, + /* For each iterator we expand, we set UNKNOWN_MODE_ATTR to NULL. + If apply_iterator_rtx finds an unknown attribute for a mode, it will set it to the attribute. We want to know whether the attribute is unknown after we have expanded all - possible macros, so setting it to NULL here gives us the + possible iterators, so setting it to NULL here gives us the right result when the hash table traversal is complete. */ mtd->unknown_mode_attr = NULL; original = XEXP (elem, 0); - for (v = macro->values; v != 0; v = v->next) + for (v = iterator->values; v != 0; v = v->next) { - x = apply_macro_to_rtx (original, macro, v->number, - mtd->mode_maps, mtd->infile, - &mtd->unknown_mode_attr); + x = apply_iterator_to_rtx (original, iterator, v->number, + mtd->mode_maps, + &mtd->unknown_mode_attr); add_condition_to_rtx (x, v->string); - if (v != macro->values) + if (v != iterator->values) { /* Insert a new EXPR_LIST node after ELEM and put the new expansion there. */ @@ -613,12 +513,10 @@ apply_macro_traverse (void **slot, void *data) } /* Add a new "mapping" structure to hashtable TABLE. NAME is the name - of the mapping, GROUP is the group to which it belongs, and INFILE - is the file that defined the mapping. */ + of the mapping and GROUP is the group to which it belongs. */ static struct mapping * -add_mapping (struct macro_group *group, htab_t table, - const char *name, FILE *infile) +add_mapping (struct iterator_group *group, htab_t table, const char *name) { struct mapping *m; void **slot; @@ -631,7 +529,7 @@ add_mapping (struct macro_group *group, htab_t table, slot = htab_find_slot (table, m, INSERT); if (*slot != 0) - fatal_with_file_and_line (infile, "`%s' already defined", name); + fatal_with_file_and_line ("`%s' already defined", name); *slot = m; return m; @@ -658,29 +556,31 @@ add_map_value (struct map_value **end_ptr, int number, const char *string) /* Do one-time initialization of the mode and code attributes. */ static void -initialize_macros (void) +initialize_iterators (void) { struct mapping *lower, *upper; struct map_value **lower_ptr, **upper_ptr; char *copy, *p; int i; - modes.attrs = htab_create (13, def_hash, def_name_eq_p, 0); - modes.macros = htab_create (13, def_hash, def_name_eq_p, 0); + modes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0); + modes.iterators = htab_create (13, leading_string_hash, + leading_string_eq_p, 0); modes.num_builtins = MAX_MACHINE_MODE; modes.find_builtin = find_mode; - modes.uses_macro_p = uses_mode_macro_p; - modes.apply_macro = apply_mode_macro; + modes.uses_iterator_p = uses_mode_iterator_p; + modes.apply_iterator = apply_mode_iterator; - codes.attrs = htab_create (13, def_hash, def_name_eq_p, 0); - codes.macros = htab_create (13, def_hash, def_name_eq_p, 0); + codes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0); + codes.iterators = htab_create (13, leading_string_hash, + leading_string_eq_p, 0); codes.num_builtins = NUM_RTX_CODE; codes.find_builtin = find_code; - codes.uses_macro_p = uses_code_macro_p; - codes.apply_macro = apply_code_macro; + codes.uses_iterator_p = uses_code_iterator_p; + codes.apply_iterator = apply_code_iterator; - lower = add_mapping (&modes, modes.attrs, "mode", 0); - upper = add_mapping (&modes, modes.attrs, "MODE", 0); + lower = add_mapping (&modes, modes.attrs, "mode"); + upper = add_mapping (&modes, modes.attrs, "MODE"); lower_ptr = &lower->values; upper_ptr = &upper->values; for (i = 0; i < MAX_MACHINE_MODE; i++) @@ -693,8 +593,8 @@ initialize_macros (void) lower_ptr = add_map_value (lower_ptr, i, copy); } - lower = add_mapping (&codes, codes.attrs, "code", 0); - upper = add_mapping (&codes, codes.attrs, "CODE", 0); + lower = add_mapping (&codes, codes.attrs, "code"); + upper = add_mapping (&codes, codes.attrs, "CODE"); lower_ptr = &lower->values; upper_ptr = &upper->values; for (i = 0; i < NUM_RTX_CODE; i++) @@ -707,381 +607,6 @@ initialize_macros (void) upper_ptr = add_map_value (upper_ptr, i, copy); } } - -/* Return a hash value for the pointer pointed to by DEF. */ - -static hashval_t -leading_ptr_hash (const void *def) -{ - return htab_hash_pointer (*(const void *const *) def); -} - -/* Return true if DEF1 and DEF2 are pointers to the same pointer. */ - -static int -leading_ptr_eq_p (const void *def1, const void *def2) -{ - return *(const void *const *) def1 == *(const void *const *) def2; -} - -/* Associate PTR with the file position given by FILENAME and LINENO. */ - -static void -set_rtx_ptr_loc (const void *ptr, const char *filename, int lineno) -{ - struct ptr_loc *loc; - - loc = (struct ptr_loc *) obstack_alloc (&ptr_loc_obstack, - sizeof (struct ptr_loc)); - loc->ptr = ptr; - loc->filename = filename; - loc->lineno = lineno; - *htab_find_slot (ptr_locs, loc, INSERT) = loc; -} - -/* Return the position associated with pointer PTR. Return null if no - position was set. */ - -static const struct ptr_loc * -get_rtx_ptr_loc (const void *ptr) -{ - return (const struct ptr_loc *) htab_find (ptr_locs, &ptr); -} - -/* Associate NEW_PTR with the same file position as OLD_PTR. */ - -void -copy_rtx_ptr_loc (const void *new_ptr, const void *old_ptr) -{ - const struct ptr_loc *loc = get_rtx_ptr_loc (old_ptr); - if (loc != 0) - set_rtx_ptr_loc (new_ptr, loc->filename, loc->lineno); -} - -/* If PTR is associated with a known file position, print a #line - directive for it. */ - -void -print_rtx_ptr_loc (const void *ptr) -{ - const struct ptr_loc *loc = get_rtx_ptr_loc (ptr); - if (loc != 0) - printf ("#line %d \"%s\"\n", loc->lineno, loc->filename); -} - -/* Return a condition that satisfies both COND1 and COND2. Either string - may be null or empty. */ - -const char * -join_c_conditions (const char *cond1, const char *cond2) -{ - char *result; - const void **entry; - - if (cond1 == 0 || cond1[0] == 0) - return cond2; - - if (cond2 == 0 || cond2[0] == 0) - return cond1; - - result = concat ("(", cond1, ") && (", cond2, ")", NULL); - obstack_ptr_grow (&joined_conditions_obstack, result); - obstack_ptr_grow (&joined_conditions_obstack, cond1); - obstack_ptr_grow (&joined_conditions_obstack, cond2); - entry = XOBFINISH (&joined_conditions_obstack, const void **); - *htab_find_slot (joined_conditions, entry, INSERT) = entry; - return result; -} - -/* Print condition COND, wrapped in brackets. If COND was created by - join_c_conditions, recursively invoke this function for the original - conditions and join the result with "&&". Otherwise print a #line - directive for COND if its original file position is known. */ - -void -print_c_condition (const char *cond) -{ - const char **halves = (const char **) htab_find (joined_conditions, &cond); - if (halves != 0) - { - printf ("("); - print_c_condition (halves[1]); - printf (" && "); - print_c_condition (halves[2]); - printf (")"); - } - else - { - putc ('\n', stdout); - print_rtx_ptr_loc (cond); - printf ("(%s)", cond); - } -} - -/* 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 (FILE *infile) -{ - 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 '/': - { - 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 (char *str, FILE *infile) -{ - char *p; - int c; - - c = read_skip_spaces (infile); - - p = str; - while (1) - { - if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r' || c == EOF) - 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 = (struct md_constant *) htab_find (md_constants, &tmp_def); - if (def) - p = def->value; - } while (def); - if (p != str) - strcpy (str, p); - } -} - -/* Subroutine of the string readers. Handles backslash escapes. - Caller has read the backslash, but not placed it into the obstack. */ -static void -read_escape (FILE *infile) -{ - int c = getc (infile); - - switch (c) - { - /* Backslash-newline is replaced by nothing, as in C. */ - case '\n': - read_rtx_lineno++; - return; - - /* \" \' \\ are replaced by the second character. */ - case '\\': - case '"': - case '\'': - break; - - /* Standard C string escapes: - \a \b \f \n \r \t \v - \[0-7] \x - all are passed through to the output string unmolested. - In normal use these wind up in a string constant processed - by the C compiler, which will translate them appropriately. - We do not bother checking that \[0-7] are followed by up to - two octal digits, or that \x is followed by N hex digits. - \? \u \U are left out because they are not in traditional C. */ - case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v': - case '0': case '1': case '2': case '3': case '4': case '5': case '6': - case '7': case 'x': - obstack_1grow (&string_obstack, '\\'); - break; - - /* \; makes stuff for a C string constant containing - newline and tab. */ - case ';': - obstack_grow (&string_obstack, "\\n\\t", 4); - return; - - /* pass anything else through, but issue a warning. */ - default: - fprintf (stderr, "%s:%d: warning: unrecognized escape \\%c\n", - read_rtx_filename, read_rtx_lineno, c); - obstack_1grow (&string_obstack, '\\'); - break; - } - - obstack_1grow (&string_obstack, c); -} - - -/* Read a double-quoted string onto the obstack. Caller has scanned - the leading quote. */ -static char * -read_quoted_string (FILE *infile) -{ - int c; - - while (1) - { - c = getc (infile); /* Read the string */ - if (c == '\n') - read_rtx_lineno++; - else if (c == '\\') - { - read_escape (infile); - continue; - } - else if (c == '"' || c == EOF) - break; - - obstack_1grow (&string_obstack, c); - } - - obstack_1grow (&string_obstack, 0); - return XOBFINISH (&string_obstack, char *); -} - -/* Read a braced string (a la Tcl) onto the string obstack. Caller - has scanned the leading brace. Note that unlike quoted strings, - the outermost braces _are_ included in the string constant. */ -static char * -read_braced_string (FILE *infile) -{ - int c; - int brace_depth = 1; /* caller-processed */ - unsigned long starting_read_rtx_lineno = read_rtx_lineno; - - obstack_1grow (&string_obstack, '{'); - while (brace_depth) - { - c = getc (infile); /* Read the string */ - - if (c == '\n') - read_rtx_lineno++; - else if (c == '{') - brace_depth++; - else if (c == '}') - brace_depth--; - else if (c == '\\') - { - read_escape (infile); - continue; - } - else if (c == EOF) - fatal_with_file_and_line - (infile, "missing closing } for opening brace on line %lu", - starting_read_rtx_lineno); - - obstack_1grow (&string_obstack, c); - } - - obstack_1grow (&string_obstack, 0); - return XOBFINISH (&string_obstack, char *); -} - -/* Read some kind of string constant. This is the high-level routine - used by read_rtx. It handles surrounding parentheses, leading star, - and dispatch to the appropriate string constant reader. */ - -static char * -read_string (FILE *infile, int star_if_braced) -{ - char *stringbuf; - int saw_paren = 0; - int c, old_lineno; - - c = read_skip_spaces (infile); - if (c == '(') - { - saw_paren = 1; - c = read_skip_spaces (infile); - } - - old_lineno = read_rtx_lineno; - if (c == '"') - stringbuf = read_quoted_string (infile); - else if (c == '{') - { - if (star_if_braced) - obstack_1grow (&string_obstack, '*'); - stringbuf = read_braced_string (infile); - } - else - fatal_with_file_and_line (infile, "expected `\"' or `{', found `%c'", c); - - if (saw_paren) - { - c = read_skip_spaces (infile); - if (c != ')') - fatal_expected_char (infile, ')', c); - } - - set_rtx_ptr_loc (stringbuf, read_rtx_filename, old_lineno); - return stringbuf; -} /* Provide a version of a function to read a long long if the system does not provide one. */ @@ -1120,99 +645,9 @@ atoll (const char *p) return tmp_wide; } #endif - -/* Given an object that starts with a char * name field, return a hash - code for its name. */ -static hashval_t -def_hash (const void *def) -{ - unsigned result, i; - const char *string = *(const char *const *) def; - - for (result = i = 0; *string++ != '\0'; i++) - result += ((unsigned char) *string << (i % CHAR_BIT)); - return result; -} - -/* Given two objects that start with char * name fields, return true if - they have the same name. */ -static int -def_name_eq_p (const void *def1, const void *def2) -{ - return ! strcmp (*(const char *const *) def1, - *(const char *const *) def2); -} - -/* 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 (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 = XNEW (struct md_constant); - def->name = tmp_char; - read_name (tmp_char, infile); - entry_ptr = htab_find_slot (defs, def, INSERT); - 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 = (struct md_constant *) *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 (htab_trav callback, void *info) -{ - if (md_constants) - htab_traverse (md_constants, callback, info); -} -/* 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_conditions directive, starting with the optional space after - the "define_conditions". The directive looks like this: +/* Process a define_conditions directive, starting with the optional + space after the "define_conditions". The directive looks like this: (define_conditions [ (number "string") @@ -1225,44 +660,42 @@ traverse_md_constants (htab_trav callback, void *info) slipped in at the beginning of the sequence of MD files read by most of the other generators. */ static void -read_conditions (FILE *infile, char *tmp_char) +read_conditions (void) { int c; - c = read_skip_spaces (infile); + c = read_skip_spaces (); if (c != '[') - fatal_expected_char (infile, '[', c); + fatal_expected_char ('[', c); - while ( (c = read_skip_spaces (infile)) != ']') + while ( (c = read_skip_spaces ()) != ']') { + struct md_name name; char *expr; int value; if (c != '(') - fatal_expected_char (infile, '(', c); + fatal_expected_char ('(', c); - read_name (tmp_char, infile); - validate_const_int (infile, tmp_char); - value = atoi (tmp_char); + read_name (&name); + validate_const_int (name.string); + value = atoi (name.string); - c = read_skip_spaces (infile); + c = read_skip_spaces (); if (c != '"') - fatal_expected_char (infile, '"', c); - expr = read_quoted_string (infile); + fatal_expected_char ('"', c); + expr = read_quoted_string (); - c = read_skip_spaces (infile); + c = read_skip_spaces (); if (c != ')') - fatal_expected_char (infile, ')', c); + fatal_expected_char (')', c); add_c_test (expr, value); } - c = read_skip_spaces (infile); - if (c != ')') - fatal_expected_char (infile, ')', c); } static void -validate_const_int (FILE *infile, const char *string) +validate_const_int (const char *string) { const char *cp; int valid = 1; @@ -1278,188 +711,176 @@ validate_const_int (FILE *infile, const char *string) if (! ISDIGIT (*cp)) valid = 0; if (!valid) - fatal_with_file_and_line (infile, "invalid decimal constant \"%s\"\n", string); + fatal_with_file_and_line ("invalid decimal constant \"%s\"\n", string); } /* Search GROUP for a mode or code called NAME and return its numerical - identifier. INFILE is the file that contained NAME. */ + identifier. */ static int -find_macro (struct macro_group *group, const char *name, FILE *infile) +find_iterator (struct iterator_group *group, const char *name) { struct mapping *m; - m = (struct mapping *) htab_find (group->macros, &name); + m = (struct mapping *) htab_find (group->iterators, &name); if (m != 0) return m->index + group->num_builtins; - return group->find_builtin (name, infile); + return group->find_builtin (name); } /* Finish reading a declaration of the form: (define... [ ... ]) - from INFILE, where each is either a bare symbol name or a + from the MD file, where each is either a bare symbol name or a "( )" pair. The "(define..." part has already been read. Represent the declaration as a "mapping" structure; add it to TABLE (which belongs to GROUP) and return it. */ static struct mapping * -read_mapping (struct macro_group *group, htab_t table, FILE *infile) +read_mapping (struct iterator_group *group, htab_t table) { - char tmp_char[256]; + struct md_name name; struct mapping *m; struct map_value **end_ptr; const char *string; int number, c; /* Read the mapping name and create a structure for it. */ - read_name (tmp_char, infile); - m = add_mapping (group, table, tmp_char, infile); + read_name (&name); + m = add_mapping (group, table, name.string); - c = read_skip_spaces (infile); + c = read_skip_spaces (); if (c != '[') - fatal_expected_char (infile, '[', c); + fatal_expected_char ('[', c); /* Read each value. */ end_ptr = &m->values; - c = read_skip_spaces (infile); + c = read_skip_spaces (); do { if (c != '(') { /* A bare symbol name that is implicitly paired to an empty string. */ - ungetc (c, infile); - read_name (tmp_char, infile); + unread_char (c); + read_name (&name); string = ""; } else { /* A "(name string)" pair. */ - read_name (tmp_char, infile); - string = read_string (infile, false); - c = read_skip_spaces (infile); + read_name (&name); + string = read_string (false); + c = read_skip_spaces (); if (c != ')') - fatal_expected_char (infile, ')', c); + fatal_expected_char (')', c); } - number = group->find_builtin (tmp_char, infile); + number = group->find_builtin (name.string); end_ptr = add_map_value (end_ptr, number, string); - c = read_skip_spaces (infile); + c = read_skip_spaces (); } while (c != ']'); - c = read_skip_spaces (infile); - if (c != ')') - fatal_expected_char (infile, ')', c); - return m; } -/* Check newly-created code macro MACRO to see whether every code has the - same format. Initialize the macro's entry in bellwether_codes. */ +/* Check newly-created code iterator ITERATOR to see whether every code has the + same format. Initialize the iterator's entry in bellwether_codes. */ static void -check_code_macro (struct mapping *macro, FILE *infile) +check_code_iterator (struct mapping *iterator) { struct map_value *v; enum rtx_code bellwether; - bellwether = (enum rtx_code) macro->values->number; - for (v = macro->values->next; v != 0; v = v->next) + bellwether = (enum rtx_code) iterator->values->number; + for (v = iterator->values->next; v != 0; v = v->next) if (strcmp (GET_RTX_FORMAT (bellwether), GET_RTX_FORMAT (v->number)) != 0) - fatal_with_file_and_line (infile, "code macro `%s' combines " - "different rtx formats", macro->name); + fatal_with_file_and_line ("code iterator `%s' combines " + "different rtx formats", iterator->name); bellwether_codes = XRESIZEVEC (enum rtx_code, bellwether_codes, - macro->index + 1); - bellwether_codes[macro->index] = bellwether; + iterator->index + 1); + bellwether_codes[iterator->index] = bellwether; } -/* Read an rtx in printed representation from INFILE and store its - core representation in *X. Also store the line number of the - opening '(' in *LINENO. Return true on success or false if the - end of file has been reached. - - read_rtx is not used in the compiler proper, but rather in - the utilities gen*.c that construct C code from machine descriptions. */ +/* Read an rtx-related declaration from the MD file, given that it + starts with directive name RTX_NAME. Return true if it expands to + one or more rtxes (as defined by rtx.def). When returning true, + store the list of rtxes as an EXPR_LIST in *X. */ bool -read_rtx (FILE *infile, rtx *x, int *lineno) +read_rtx (const char *rtx_name, rtx *x) { - static rtx queue_head, queue_next; - static int queue_lineno; - int c; + static rtx queue_head; + struct map_value *mode_maps; + struct iterator_traverse_data mtd; /* Do one-time initialization. */ if (queue_head == 0) { - initialize_macros (); - obstack_init (&string_obstack); + initialize_iterators (); queue_head = rtx_alloc (EXPR_LIST); - ptr_locs = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0); - obstack_init (&ptr_loc_obstack); - joined_conditions = htab_create (161, leading_ptr_hash, - leading_ptr_eq_p, 0); - obstack_init (&joined_conditions_obstack); } - if (queue_next == 0) + /* Handle various rtx-related declarations that aren't themselves + encoded as rtxes. */ + if (strcmp (rtx_name, "define_conditions") == 0) + { + read_conditions (); + return false; + } + if (strcmp (rtx_name, "define_mode_attr") == 0) { - struct map_value *mode_maps; - struct macro_traverse_data mtd; - rtx from_file; - - c = read_skip_spaces (infile); - if (c == EOF) - return false; - ungetc (c, infile); - - queue_lineno = read_rtx_lineno; - mode_maps = 0; - from_file = read_rtx_1 (infile, &mode_maps); - if (from_file == 0) - return false; /* This confuses a top level (nil) with end of - file, but a top level (nil) would have - crashed our caller anyway. */ - - queue_next = queue_head; - XEXP (queue_next, 0) = from_file; - XEXP (queue_next, 1) = 0; - - mtd.queue = queue_next; - mtd.mode_maps = mode_maps; - mtd.infile = infile; - mtd.unknown_mode_attr = mode_maps ? mode_maps->string : NULL; - htab_traverse (modes.macros, apply_macro_traverse, &mtd); - htab_traverse (codes.macros, apply_macro_traverse, &mtd); - if (mtd.unknown_mode_attr) - fatal_with_file_and_line (infile, - "undefined attribute '%s' used for mode", - mtd.unknown_mode_attr); + read_mapping (&modes, modes.attrs); + return false; + } + if (strcmp (rtx_name, "define_mode_iterator") == 0) + { + read_mapping (&modes, modes.iterators); + return false; + } + if (strcmp (rtx_name, "define_code_attr") == 0) + { + read_mapping (&codes, codes.attrs); + return false; + } + if (strcmp (rtx_name, "define_code_iterator") == 0) + { + check_code_iterator (read_mapping (&codes, codes.iterators)); + return false; } - *x = XEXP (queue_next, 0); - *lineno = queue_lineno; - queue_next = XEXP (queue_next, 1); + mode_maps = 0; + XEXP (queue_head, 0) = read_rtx_code (rtx_name, &mode_maps); + XEXP (queue_head, 1) = 0; + mtd.queue = queue_head; + mtd.mode_maps = mode_maps; + mtd.unknown_mode_attr = mode_maps ? mode_maps->string : NULL; + htab_traverse (modes.iterators, apply_iterator_traverse, &mtd); + htab_traverse (codes.iterators, apply_iterator_traverse, &mtd); + if (mtd.unknown_mode_attr) + fatal_with_file_and_line ("undefined attribute '%s' used for mode", + mtd.unknown_mode_attr); + + *x = queue_head; return true; } -/* Subroutine of read_rtx that reads one construct from INFILE but - doesn't apply any macros. */ +/* Subroutine of read_rtx and read_nested_rtx. CODE_NAME is the name of + either an rtx code or a code iterator. Parse the rest of the rtx and + return it. MODE_MAPS is as for iterator_traverse_data. */ static rtx -read_rtx_1 (FILE *infile, struct map_value **mode_maps) +read_rtx_code (const char *code_name, struct map_value **mode_maps) { int i; RTX_CODE real_code, bellwether_code; 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]; + struct md_name name; rtx return_rtx; int c; int tmp_int; @@ -1472,55 +893,7 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps) rtx value; /* Value of this node. */ }; - again: - c = read_skip_spaces (infile); /* Should be open paren. */ - - if (c == EOF) - return 0; - - if (c != '(') - fatal_expected_char (infile, '(', c); - - read_name (tmp_char, infile); - if (strcmp (tmp_char, "nil") == 0) - { - /* (nil) stands for an expression that isn't there. */ - c = read_skip_spaces (infile); - if (c != ')') - fatal_expected_char (infile, ')', c); - return 0; - } - if (strcmp (tmp_char, "define_constants") == 0) - { - read_constants (infile, tmp_char); - goto again; - } - if (strcmp (tmp_char, "define_conditions") == 0) - { - read_conditions (infile, tmp_char); - goto again; - } - if (strcmp (tmp_char, "define_mode_attr") == 0) - { - read_mapping (&modes, modes.attrs, infile); - goto again; - } - if (strcmp (tmp_char, "define_mode_macro") == 0) - { - read_mapping (&modes, modes.macros, infile); - goto again; - } - if (strcmp (tmp_char, "define_code_attr") == 0) - { - read_mapping (&codes, codes.attrs, infile); - goto again; - } - if (strcmp (tmp_char, "define_code_macro") == 0) - { - check_code_macro (read_mapping (&codes, codes.macros, infile), infile); - goto again; - } - real_code = (enum rtx_code) find_macro (&codes, tmp_char, infile); + real_code = (enum rtx_code) find_iterator (&codes, code_name); bellwether_code = BELLWETHER_CODE (real_code); /* If we end up with an insn expression then we free this space below. */ @@ -1531,22 +904,22 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps) /* If what follows is `: mode ', read it and store the mode in the rtx. */ - i = read_skip_spaces (infile); + i = read_skip_spaces (); if (i == ':') { unsigned int mode; - read_name (tmp_char, infile); - if (tmp_char[0] != '<' || tmp_char[strlen (tmp_char) - 1] != '>') - mode = find_macro (&modes, tmp_char, infile); + read_name (&name); + if (name.string[0] != '<' || name.string[strlen (name.string) - 1] != '>') + mode = find_iterator (&modes, name.string); else - mode = mode_attr_index (mode_maps, tmp_char); + mode = mode_attr_index (mode_maps, name.string); PUT_MODE (return_rtx, (enum machine_mode) mode); if (GET_MODE (return_rtx) != mode) - fatal_with_file_and_line (infile, "mode too large"); + fatal_with_file_and_line ("mode too large"); } else - ungetc (i, infile); + unread_char (i); for (i = 0; format_ptr[i] != 0; i++) switch (format_ptr[i]) @@ -1558,14 +931,14 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps) case 'e': case 'u': - XEXP (return_rtx, i) = read_rtx_1 (infile, mode_maps); + XEXP (return_rtx, i) = read_nested_rtx (mode_maps); 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); + c = read_skip_spaces (); + unread_char (c); if (c == ')') { XVEC (return_rtx, i) = 0; @@ -1580,17 +953,19 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps) int list_counter = 0; rtvec return_vec = NULL_RTVEC; - c = read_skip_spaces (infile); + c = read_skip_spaces (); if (c != '[') - fatal_expected_char (infile, '[', c); + fatal_expected_char ('[', c); /* Add expressions to a list, while keeping a count. */ obstack_init (&vector_stack); - while ((c = read_skip_spaces (infile)) && c != ']') + while ((c = read_skip_spaces ()) && c != ']') { - ungetc (c, infile); + if (c == EOF) + fatal_expected_char (']', c); + unread_char (c); list_counter++; - obstack_ptr_grow (&vector_stack, read_rtx_1 (infile, mode_maps)); + obstack_ptr_grow (&vector_stack, read_nested_rtx (mode_maps)); } if (list_counter > 0) { @@ -1599,8 +974,7 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps) list_counter * sizeof (rtx)); } else if (format_ptr[i] == 'E') - fatal_with_file_and_line (infile, - "vector must have at least one element"); + fatal_with_file_and_line ("vector must have at least one element"); XVEC (return_rtx, i) = return_vec; obstack_free (&vector_stack, NULL); /* close bracket gotten */ @@ -1614,8 +988,8 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps) char *stringbuf; int star_if_braced; - c = read_skip_spaces (infile); - ungetc (c, infile); + c = read_skip_spaces (); + unread_char (c); if (c == ')') { /* 'S' fields are optional and should be NULL if no string @@ -1631,7 +1005,7 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps) written with a brace block instead of a string constant. */ star_if_braced = (format_ptr[i] == 'T'); - stringbuf = read_string (infile, star_if_braced); + stringbuf = read_string (star_if_braced); /* For insn patterns, we want to provide a default name based on the file and line, like "*foo.md:12", if the @@ -1643,14 +1017,14 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps) || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT)) { char line_name[20]; - const char *fn = (read_rtx_filename ? read_rtx_filename : "rtx"); + const char *fn = (read_md_filename ? read_md_filename : "rtx"); const char *slash; for (slash = fn; *slash; slash ++) if (*slash == '/' || *slash == '\\' || *slash == ':') fn = slash + 1; obstack_1grow (&string_obstack, '*'); obstack_grow (&string_obstack, fn, strlen (fn)); - sprintf (line_name, ":%d", read_rtx_lineno); + sprintf (line_name, ":%d", read_md_lineno); obstack_grow (&string_obstack, line_name, strlen (line_name)+1); stringbuf = XOBFINISH (&string_obstack, char *); } @@ -1663,20 +1037,20 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps) break; case 'w': - read_name (tmp_char, infile); - validate_const_int (infile, tmp_char); + read_name (&name); + validate_const_int (name.string); #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT - tmp_wide = atoi (tmp_char); + tmp_wide = atoi (name.string); #else #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG - tmp_wide = atol (tmp_char); + tmp_wide = atol (name.string); #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); + tmp_wide = atoll (name.string); #else - tmp_wide = atoq (tmp_char); + tmp_wide = atoq (name.string); #endif #endif #endif @@ -1685,9 +1059,9 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps) case 'i': case 'n': - read_name (tmp_char, infile); - validate_const_int (infile, tmp_char); - tmp_int = atoi (tmp_char); + read_name (&name); + validate_const_int (name.string); + tmp_int = atoi (name.string); XINT (return_rtx, i) = tmp_int; break; @@ -1695,17 +1069,41 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps) gcc_unreachable (); } - c = read_skip_spaces (infile); + c = read_skip_spaces (); + /* Syntactic sugar for AND and IOR, allowing Lisp-like + arbitrary number of arguments for them. */ + if (c == '(' + && (GET_CODE (return_rtx) == AND + || GET_CODE (return_rtx) == IOR)) + return read_rtx_variadic (mode_maps, return_rtx); + + unread_char (c); + return return_rtx; +} + +/* Read a nested rtx construct from the MD file and return it. + MODE_MAPS is as for iterator_traverse_data. */ + +static rtx +read_nested_rtx (struct map_value **mode_maps) +{ + struct md_name name; + int c; + rtx return_rtx; + + c = read_skip_spaces (); + if (c != '(') + fatal_expected_char ('(', c); + + read_name (&name); + if (strcmp (name.string, "nil") == 0) + return_rtx = NULL; + else + return_rtx = read_rtx_code (name.string, mode_maps); + + c = read_skip_spaces (); if (c != ')') - { - /* Syntactic sugar for AND and IOR, allowing Lisp-like - arbitrary number of arguments for them. */ - if (c == '(' && (GET_CODE (return_rtx) == AND - || GET_CODE (return_rtx) == IOR)) - return read_rtx_variadic (infile, mode_maps, return_rtx); - else - fatal_expected_char (infile, ')', c); - } + fatal_expected_char (')', c); return return_rtx; } @@ -1717,29 +1115,26 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps) is just past the leading parenthesis of x3. Only works for THINGs which are dyadic expressions, e.g. AND, IOR. */ static rtx -read_rtx_variadic (FILE *infile, struct map_value **mode_maps, rtx form) +read_rtx_variadic (struct map_value **mode_maps, rtx form) { char c = '('; rtx p = form, q; do { - ungetc (c, infile); + unread_char (c); q = rtx_alloc (GET_CODE (p)); PUT_MODE (q, GET_MODE (p)); XEXP (q, 0) = XEXP (p, 1); - XEXP (q, 1) = read_rtx_1 (infile, mode_maps); - + XEXP (q, 1) = read_nested_rtx (mode_maps); + XEXP (p, 1) = q; p = q; - c = read_skip_spaces (infile); + c = read_skip_spaces (); } while (c == '('); - - if (c != ')') - fatal_expected_char (infile, ')', c); - + unread_char (c); return form; }