#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;
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_iterator_p) (rtx, int);
void (*apply_iterator) (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;
-};
-
/* A structure used to pass data from read_rtx to apply_iterator_traverse
via htab_traverse. */
struct iterator_traverse_data {
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;
};
#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 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 *, FILE *);
+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 *, FILE *, const char **);
+ 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_iterator_traverse (void **, void *);
static struct mapping *add_mapping (struct iterator_group *, htab_t t,
- const char *, FILE *);
+ const char *);
static struct map_value **add_map_value (struct map_value **,
int, const char *);
static void initialize_iterators (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_iterator (struct iterator_group *, const char *, FILE *);
-static struct mapping *read_mapping (struct iterator_group *, htab_t, FILE *);
-static void check_code_iterator (struct mapping *, FILE *);
-static rtx read_rtx_1 (FILE *, struct map_value **);
-static rtx read_rtx_variadic (FILE *, struct map_value **, rtx);
+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 = "<unknown>";
-
-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)
-{
- if (actual_c == EOF)
- fatal_with_file_and_line (infile, "expected character `%c', found EOF",
- expected_c);
- else
- fatal_with_file_and_line (infile, "expected character `%c', found `%c'",
- expected_c, actual_c);
-}
-
/* Implementations of the iterator_group callbacks for modes. */
static int
-find_mode (const char *name, FILE *infile)
+find_mode (const char *name)
{
int i;
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
/* Implementations of the iterator_group callbacks for codes. */
static int
-find_code (const char *name, FILE *infile)
+find_code (const char *name)
{
int i;
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
/* Apply MODE_MAPS to the top level of X, expanding cases where an
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 *iterator,
- int value, FILE *infile, const char **unknown)
+ int value, const char **unknown)
{
unsigned int offset;
int indx;
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;
{
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 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_iterator_to_rtx (rtx original, struct mapping *iterator, int value,
- struct map_value *mode_maps, FILE *infile,
+ struct map_value *mode_maps,
const char **unknown_mode_attr)
{
struct iterator_group *group;
group->apply_iterator (x, value);
if (mode_maps)
- apply_mode_maps (x, mode_maps, iterator, 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);
case 'e':
XEXP (x, i) = apply_iterator_to_rtx (XEXP (x, i), iterator, value,
- mode_maps, infile,
- unknown_mode_attr);
+ mode_maps, unknown_mode_attr);
break;
case 'V':
for (j = 0; j < XVECLEN (x, i); j++)
XVECEXP (x, i, j) = apply_iterator_to_rtx (XVECEXP (original, i, j),
iterator, value, mode_maps,
- infile,
unknown_mode_attr);
}
break;
for (v = iterator->values; v != 0; v = v->next)
{
x = apply_iterator_to_rtx (original, iterator, v->number,
- mtd->mode_maps, mtd->infile,
+ mtd->mode_maps,
&mtd->unknown_mode_attr);
add_condition_to_rtx (x, v->string);
if (v != iterator->values)
}
/* 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 iterator_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;
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;
char *copy, *p;
int i;
- modes.attrs = htab_create (13, def_hash, def_name_eq_p, 0);
- modes.iterators = 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_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.iterators = 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_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++)
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++)
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;
-
- if (strcmp (cond1, cond2) == 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;
-}
\f
/* Provide a version of a function to read a long long if the system does
not provide one. */
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);
-}
\f
-/* 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")
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;
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_iterator (struct iterator_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->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... <name> [<value1> ... <valuen>])
- from INFILE, where each <valuei> is either a bare symbol name or a
+ from the MD file, where each <valuei> is either a bare symbol name or a
"(<name> <string>)" 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 iterator_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;
}
same format. Initialize the iterator's entry in bellwether_codes. */
static void
-check_code_iterator (struct mapping *iterator, FILE *infile)
+check_code_iterator (struct mapping *iterator)
{
struct map_value *v;
enum rtx_code bellwether;
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 iterator `%s' combines "
+ fatal_with_file_and_line ("code iterator `%s' combines "
"different rtx formats", iterator->name);
bellwether_codes = XRESIZEVEC (enum rtx_code, bellwether_codes,
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_iterators ();
- obstack_init (&string_obstack);
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)
+ {
+ 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)
{
- struct map_value *mode_maps;
- struct iterator_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.iterators, apply_iterator_traverse, &mtd);
- htab_traverse (codes.iterators, apply_iterator_traverse, &mtd);
- if (mtd.unknown_mode_attr)
- fatal_with_file_and_line (infile,
- "undefined attribute '%s' used for mode",
- mtd.unknown_mode_attr);
+ 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 iterators. */
+/* 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;
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_iterator") == 0)
- {
- read_mapping (&modes, modes.iterators, 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_iterator") == 0)
- {
- check_code_iterator (read_mapping (&codes, codes.iterators, infile),
- infile);
- goto again;
- }
- real_code = (enum rtx_code) find_iterator (&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. */
/* 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_iterator (&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])
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;
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)
{
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 */
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
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
|| 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 *);
}
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
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;
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;
}
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;
}