#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;
static struct map_value **add_map_value (struct map_value **,
int, const char *);
static void initialize_iterators (void);
-static void read_name (char *);
-static hashval_t def_hash (const void *);
-static int def_name_eq_p (const void *, const void *);
-static void read_constants (char *tmp_char);
-static void read_conditions (char *tmp_char);
+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_1 (struct map_value **);
+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. */
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;
upper_ptr = add_map_value (upper_ptr, i, copy);
}
}
-
-/* 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)
-{
- char *p;
- int c;
-
- c = read_skip_spaces ();
-
- 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 == '[')
- {
- unread_char (c);
- break;
- }
- *p++ = c;
- c = read_char ();
- }
- if (p == str)
- fatal_with_file_and_line ("missing name or number");
- if (c == '\n')
- read_md_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);
- }
-}
\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);
-}
-
-/* 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 (char *tmp_char)
-{
- int c;
- htab_t defs;
-
- c = read_skip_spaces ();
- if (c != '[')
- fatal_expected_char ('[', 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 ()) != ']')
- {
- struct md_constant *def;
- void **entry_ptr;
-
- if (c != '(')
- fatal_expected_char ('(', c);
- def = XNEW (struct md_constant);
- def->name = tmp_char;
- read_name (tmp_char);
- entry_ptr = htab_find_slot (defs, def, INSERT);
- if (! *entry_ptr)
- def->name = xstrdup (tmp_char);
- read_name (tmp_char);
- 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 ("redefinition of %s, was %s, now %s",
- def->name, def->value, tmp_char);
- }
- c = read_skip_spaces ();
- if (c != ')')
- fatal_expected_char (')', c);
- }
- md_constants = defs;
- c = read_skip_spaces ();
- if (c != ')')
- fatal_expected_char (')', 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
-/* 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 (char *tmp_char)
+read_conditions (void)
{
int c;
while ( (c = read_skip_spaces ()) != ']')
{
+ struct md_name name;
char *expr;
int value;
if (c != '(')
fatal_expected_char ('(', c);
- read_name (tmp_char);
- validate_const_int (tmp_char);
- value = atoi (tmp_char);
+ read_name (&name);
+ validate_const_int (name.string);
+ value = atoi (name.string);
c = read_skip_spaces ();
if (c != '"')
add_c_test (expr, value);
}
- c = read_skip_spaces ();
- if (c != ')')
- fatal_expected_char (')', c);
}
static void
static struct mapping *
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);
- m = add_mapping (group, table, tmp_char);
+ read_name (&name);
+ m = add_mapping (group, table, name.string);
c = read_skip_spaces ();
if (c != '[')
/* A bare symbol name that is implicitly paired to an
empty string. */
unread_char (c);
- read_name (tmp_char);
+ read_name (&name);
string = "";
}
else
{
/* A "(name string)" pair. */
- read_name (tmp_char);
+ read_name (&name);
string = read_string (false);
c = read_skip_spaces ();
if (c != ')')
fatal_expected_char (')', c);
}
- number = group->find_builtin (tmp_char);
+ number = group->find_builtin (name.string);
end_ptr = add_map_value (end_ptr, number, string);
c = read_skip_spaces ();
}
while (c != ']');
- c = read_skip_spaces ();
- if (c != ')')
- fatal_expected_char (')', c);
-
return m;
}
bellwether_codes[iterator->index] = bellwether;
}
-/* Read an rtx in printed representation from the MD file 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 (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)
{
- init_md_reader ();
initialize_iterators ();
queue_head = rtx_alloc (EXPR_LIST);
}
- if (queue_next == 0)
+ /* Handle various rtx-related declarations that aren't themselves
+ encoded as rtxes. */
+ if (strcmp (rtx_name, "define_conditions") == 0)
{
- struct map_value *mode_maps;
- struct iterator_traverse_data mtd;
- rtx from_file;
-
- c = read_skip_spaces ();
- if (c == EOF)
- return false;
- unread_char (c);
-
- queue_lineno = read_md_lineno;
- mode_maps = 0;
- from_file = read_rtx_1 (&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.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);
+ 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)
+ {
+ check_code_iterator (read_mapping (&codes, codes.iterators));
+ return false;
+ }
+
+ mode_maps = 0;
+ XEXP (queue_head, 0) = read_rtx_code (rtx_name, &mode_maps);
+ XEXP (queue_head, 1) = 0;
- *x = XEXP (queue_next, 0);
- *lineno = queue_lineno;
- queue_next = XEXP (queue_next, 1);
+ 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 the MD file 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 (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 (); /* Should be open paren. */
-
- if (c == EOF)
- return 0;
-
- if (c != '(')
- fatal_expected_char ('(', c);
-
- read_name (tmp_char);
- if (strcmp (tmp_char, "nil") == 0)
- {
- /* (nil) stands for an expression that isn't there. */
- c = read_skip_spaces ();
- if (c != ')')
- fatal_expected_char (')', c);
- return 0;
- }
- if (strcmp (tmp_char, "define_constants") == 0)
- {
- read_constants (tmp_char);
- goto again;
- }
- if (strcmp (tmp_char, "define_conditions") == 0)
- {
- read_conditions (tmp_char);
- goto again;
- }
- if (strcmp (tmp_char, "define_mode_attr") == 0)
- {
- read_mapping (&modes, modes.attrs);
- goto again;
- }
- if (strcmp (tmp_char, "define_mode_iterator") == 0)
- {
- read_mapping (&modes, modes.iterators);
- goto again;
- }
- if (strcmp (tmp_char, "define_code_attr") == 0)
- {
- read_mapping (&codes, codes.attrs);
- goto again;
- }
- if (strcmp (tmp_char, "define_code_iterator") == 0)
- {
- check_code_iterator (read_mapping (&codes, codes.iterators));
- goto again;
- }
- real_code = (enum rtx_code) find_iterator (&codes, tmp_char);
+ 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. */
{
unsigned int mode;
- read_name (tmp_char);
- if (tmp_char[0] != '<' || tmp_char[strlen (tmp_char) - 1] != '>')
- mode = find_iterator (&modes, tmp_char);
+ 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 ("mode too large");
case 'e':
case 'u':
- XEXP (return_rtx, i) = read_rtx_1 (mode_maps);
+ XEXP (return_rtx, i) = read_nested_rtx (mode_maps);
break;
case 'V':
fatal_expected_char (']', c);
unread_char (c);
list_counter++;
- obstack_ptr_grow (&vector_stack, read_rtx_1 (mode_maps));
+ obstack_ptr_grow (&vector_stack, read_nested_rtx (mode_maps));
}
if (list_counter > 0)
{
break;
case 'w':
- read_name (tmp_char);
- validate_const_int (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);
- validate_const_int (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;
}
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 (mode_maps, return_rtx);
- else
- fatal_expected_char (')', c);
- }
+ fatal_expected_char (')', c);
return return_rtx;
}
PUT_MODE (q, GET_MODE (p));
XEXP (q, 0) = XEXP (p, 1);
- XEXP (q, 1) = read_rtx_1 (mode_maps);
+ XEXP (q, 1) = read_nested_rtx (mode_maps);
XEXP (p, 1) = q;
p = q;
c = read_skip_spaces ();
}
while (c == '(');
-
- if (c != ')')
- fatal_expected_char (')', c);
-
+ unread_char (c);
return form;
}