};
/* 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
+ The integers are iterator values; the strings are either C conditions
or attribute values. */
struct mapping {
/* The name of the iterator or attribute. */
/* The group (modes or codes) to which the iterator or attribute belongs. */
struct iterator_group *group;
- /* Gives a unique number to the attribute or iterator. Numbers are
- allocated consecutively, starting at 0. */
- int index;
-
/* The list of (integer, string) pairs. */
struct map_value *values;
+
+ /* For iterators, records the current value of the iterator. */
+ struct map_value *current_value;
};
-/* A structure for abstracting the common parts of code and mode iterators. */
+/* Vector definitions for the above. */
+typedef struct mapping *mapping_ptr;
+DEF_VEC_P (mapping_ptr);
+DEF_VEC_ALLOC_P (mapping_ptr, heap);
+
+/* A structure for abstracting the common parts of iterators. */
struct iterator_group {
- /* Tables of "mapping" structures, one for attributes and one for iterators. */
+ /* 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 an iterator placeholder). */
- int num_builtins;
-
- /* Treat the given string as the name of a standard mode or code and
+ /* Treat the given string as the name of a standard mode, etc., and
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);
+ /* Make the given pointer use the given iterator value. */
+ void (*apply_iterator) (void *, int);
+};
- /* Make the given rtx use the given mode or code. */
- void (*apply_iterator) (rtx, int);
+/* Records one use of an iterator. */
+struct iterator_use {
+ /* The iterator itself. */
+ struct mapping *iterator;
+
+ /* The location of the use, as passed to the apply_iterator callback. */
+ void *ptr;
};
-/* A structure used to pass data from read_rtx to apply_iterator_traverse
- via htab_traverse. */
-struct iterator_traverse_data {
- /* Instruction queue. */
- rtx queue;
- /* Attributes seen for modes. */
- struct map_value *mode_maps;
- /* The last unknown attribute used as a mode. */
- const char *unknown_mode_attr;
+/* Vector definitions for the above. */
+typedef struct iterator_use iterator_use;
+DEF_VEC_O (iterator_use);
+DEF_VEC_ALLOC_O (iterator_use, heap);
+
+/* Records one use of an attribute (the "<[iterator:]attribute>" syntax)
+ in a non-string rtx field. */
+struct attribute_use {
+ /* The group that describes the use site. */
+ struct iterator_group *group;
+
+ /* The name of the attribute, possibly with an "iterator:" prefix. */
+ const char *value;
+
+ /* The location of the use, as passed to GROUP's apply_iterator callback. */
+ void *ptr;
};
-/* 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 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_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_iterators (void);
-static void read_conditions (void);
+/* Vector definitions for the above. */
+typedef struct attribute_use attribute_use;
+DEF_VEC_O (attribute_use);
+DEF_VEC_ALLOC_O (attribute_use, heap);
+
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);
+static rtx read_rtx_code (const char *);
+static rtx read_nested_rtx (void);
+static rtx read_rtx_variadic (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;
+/* All iterators used in the current rtx. */
+static VEC (mapping_ptr, heap) *current_iterators;
+
+/* The list of all iterator uses in the current rtx. */
+static VEC (iterator_use, heap) *iterator_uses;
+
+/* The list of all attribute uses in the current rtx. */
+static VEC (attribute_use, heap) *attribute_uses;
/* Implementations of the iterator_group callbacks for modes. */
fatal_with_file_and_line ("unknown mode `%s'", name);
}
-static bool
-uses_mode_iterator_p (rtx x, int mode)
-{
- return (int) GET_MODE (x) == mode;
-}
-
static void
-apply_mode_iterator (rtx x, int mode)
+apply_mode_iterator (void *loc, int mode)
{
- PUT_MODE (x, (enum machine_mode) mode);
+ PUT_MODE ((rtx) loc, (enum machine_mode) mode);
}
/* Implementations of the iterator_group callbacks for codes. */
fatal_with_file_and_line ("unknown rtx code `%s'", name);
}
-static bool
-uses_code_iterator_p (rtx x, int code)
-{
- return (int) GET_CODE (x) == code;
-}
-
static void
-apply_code_iterator (rtx x, int code)
+apply_code_iterator (void *loc, int code)
{
- PUT_CODE (x, (enum rtx_code) code);
+ PUT_CODE ((rtx) loc, (enum rtx_code) code);
}
-/* Map a code or mode attribute string P to the underlying string for
- ITERATOR and VALUE. */
+/* Map attribute string P to its current value. Return null if the attribute
+ isn't known. */
static struct map_value *
-map_attr_string (const char *p, struct mapping *iterator, int value)
+map_attr_string (const char *p)
{
const char *attr;
+ struct mapping *iterator;
+ unsigned int i;
struct mapping *m;
struct map_value *v;
+ int iterator_name_len;
- /* If there's a "iterator:" prefix, check whether the iterator name matches.
- Set ATTR to the start of the attribute name. */
+ /* Peel off any "iterator:" prefix. Set ATTR to the start of the
+ attribute name. */
attr = strchr (p, ':');
if (attr == 0)
- attr = p;
+ {
+ iterator_name_len = -1;
+ attr = p;
+ }
else
{
- if (strncmp (p, iterator->name, attr - p) != 0
- || iterator->name[attr - p] != 0)
- return 0;
+ iterator_name_len = attr - p;
attr++;
}
- /* Find the attribute specification. */
- m = (struct mapping *) htab_find (iterator->group->attrs, &attr);
- if (m == 0)
- return 0;
-
- /* Find the attribute value for VALUE. */
- for (v = m->values; v != 0; v = v->next)
- if (v->number == value)
- break;
-
- return v;
-}
-
-/* Given an attribute string used as a machine mode, return an index
- to store in the machine mode to be translated by
- apply_iterator_to_rtx. */
-
-static unsigned int
-mode_attr_index (struct map_value **mode_maps, const char *string)
-{
- char *p;
- struct map_value *mv;
-
- /* Copy the attribute string into permanent storage, without the
- angle brackets around it. */
- obstack_grow0 (&string_obstack, string + 1, strlen (string) - 2);
- p = XOBFINISH (&string_obstack, char *);
-
- mv = XNEW (struct map_value);
- mv->number = *mode_maps == 0 ? 0 : (*mode_maps)->number + 1;
- mv->string = p;
- mv->next = *mode_maps;
- *mode_maps = mv;
-
- /* We return a code which we can map back into this string: the
- number of machine modes + the number of mode iterators + the index
- we just used. */
- 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. ITERATOR is the current iterator we are
- expanding, and VALUE is the value to which we are expanding it.
- 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, const char **unknown)
-{
- unsigned int offset;
- int indx;
- struct map_value *pm;
-
- offset = MAX_MACHINE_MODE + htab_elements (modes.iterators);
- if (GET_MODE (x) < offset)
- return;
-
- indx = GET_MODE (x) - offset;
- for (pm = mode_maps; pm; pm = pm->next)
+ FOR_EACH_VEC_ELT (mapping_ptr, current_iterators, i, iterator)
{
- if (pm->number == indx)
- {
- struct map_value *v;
+ /* If an iterator name was specified, check that it matches. */
+ if (iterator_name_len >= 0
+ && (strncmp (p, iterator->name, iterator_name_len) != 0
+ || iterator->name[iterator_name_len] != 0))
+ continue;
- v = map_attr_string (pm->string, iterator, value);
- if (v)
- PUT_MODE (x, (enum machine_mode) find_mode (v->string));
- else
- *unknown = pm->string;
- return;
- }
+ /* Find the attribute specification. */
+ m = (struct mapping *) htab_find (iterator->group->attrs, &attr);
+ if (m)
+ /* Find the attribute value associated with the current
+ iterator value. */
+ for (v = m->values; v; v = v->next)
+ if (v->number == iterator->current_value->number)
+ return v;
}
+ return NULL;
}
-/* 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. */
+/* Apply the current iterator values to STRING. Return the new string
+ if any changes were needed, otherwise return STRING itself. */
static const char *
-apply_iterator_to_string (const char *string, struct mapping *iterator, int value)
+apply_iterator_to_string (const char *string)
{
char *base, *copy, *p, *start, *end;
struct map_value *v;
p = start + 1;
*end = 0;
- v = map_attr_string (p, iterator, value);
+ v = map_attr_string (p);
*end = '>';
if (v == 0)
continue;
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. This sets *UNKNOWN_MODE_ATTR to the value of
- an unknown mode attribute, and does not change it otherwise. */
+/* Return a deep copy of X, substituting the current iterator
+ values into any strings. */
static rtx
-apply_iterator_to_rtx (rtx original, struct mapping *iterator, int value,
- struct map_value *mode_maps,
- const char **unknown_mode_attr)
+copy_rtx_for_iterators (rtx original)
{
- struct iterator_group *group;
const char *format_ptr;
int i, j;
rtx x;
- enum rtx_code bellwether_code;
if (original == 0)
return original;
/* Create a shallow copy of ORIGINAL. */
- bellwether_code = BELLWETHER_CODE (GET_CODE (original));
- x = rtx_alloc (bellwether_code);
- memcpy (x, original, RTX_CODE_SIZE (bellwether_code));
-
- /* Change the mode or code itself. */
- 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, iterator, value, unknown_mode_attr);
+ x = rtx_alloc (GET_CODE (original));
+ memcpy (x, original, RTX_CODE_SIZE (GET_CODE (original)));
/* Change each string and recursively change each rtx. */
- format_ptr = GET_RTX_FORMAT (bellwether_code);
+ format_ptr = GET_RTX_FORMAT (GET_CODE (original));
for (i = 0; format_ptr[i] != 0; i++)
switch (format_ptr[i])
{
case 'T':
- XTMPL (x, i) = apply_iterator_to_string (XTMPL (x, i), iterator, value);
+ XTMPL (x, i) = apply_iterator_to_string (XTMPL (x, i));
break;
case 'S':
case 's':
- XSTR (x, i) = apply_iterator_to_string (XSTR (x, i), iterator, value);
+ XSTR (x, i) = apply_iterator_to_string (XSTR (x, i));
break;
case 'e':
- XEXP (x, i) = apply_iterator_to_rtx (XEXP (x, i), iterator, value,
- mode_maps, unknown_mode_attr);
+ XEXP (x, i) = copy_rtx_for_iterators (XEXP (x, i));
break;
case 'V':
{
XVEC (x, i) = rtvec_alloc (XVECLEN (original, i));
for (j = 0; j < XVECLEN (x, i); j++)
- XVECEXP (x, i, j) = apply_iterator_to_rtx (XVECEXP (original, i, j),
- iterator, value, mode_maps,
- unknown_mode_attr);
+ XVECEXP (x, i, j)
+ = copy_rtx_for_iterators (XVECEXP (original, i, j));
}
break;
return x;
}
-/* Return true if X (or some subexpression of X) uses iterator ITERATOR. */
-
-static bool
-uses_iterator_p (rtx x, struct mapping *iterator)
-{
- struct iterator_group *group;
- const char *format_ptr;
- int i, j;
-
- if (x == 0)
- return false;
-
- 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)));
- for (i = 0; format_ptr[i] != 0; i++)
- switch (format_ptr[i])
- {
- case 'e':
- if (uses_iterator_p (XEXP (x, i), iterator))
- return true;
- break;
-
- case 'V':
- case 'E':
- if (XVEC (x, i))
- for (j = 0; j < XVECLEN (x, i); j++)
- if (uses_iterator_p (XVECEXP (x, i, j), iterator))
- return true;
- break;
-
- default:
- break;
- }
- return false;
-}
-
/* Return a condition that must satisfy both ORIGINAL and EXTRA. If ORIGINAL
has the form "&& ..." (as used in define_insn_and_splits), assume that
EXTRA is already satisfied. Empty strings are treated like "true". */
}
}
-/* A htab_traverse callback. Search the EXPR_LIST given by DATA
- for rtxes that use the iterator in *SLOT. Replace each such rtx
- with a list of expansions. */
+/* Apply the current iterator values to all attribute_uses. */
+
+static void
+apply_attribute_uses (void)
+{
+ struct map_value *v;
+ attribute_use *ause;
+ unsigned int i;
+
+ FOR_EACH_VEC_ELT (attribute_use, attribute_uses, i, ause)
+ {
+ v = map_attr_string (ause->value);
+ if (!v)
+ fatal_with_file_and_line ("unknown iterator value `%s'", ause->value);
+ ause->group->apply_iterator (ause->ptr,
+ ause->group->find_builtin (v->string));
+ }
+}
+
+/* A htab_traverse callback for iterators. Add all used iterators
+ to current_iterators. */
static int
-apply_iterator_traverse (void **slot, void *data)
+add_current_iterators (void **slot, void *data ATTRIBUTE_UNUSED)
{
- struct iterator_traverse_data *mtd = (struct iterator_traverse_data *) data;
struct mapping *iterator;
- struct map_value *v;
- rtx elem, new_elem, original, x;
iterator = (struct mapping *) *slot;
- for (elem = mtd->queue; elem != 0; elem = XEXP (elem, 1))
- if (uses_iterator_p (XEXP (elem, 0), iterator))
- {
- /* 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 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 = iterator->values; v != 0; v = v->next)
- {
- 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 != iterator->values)
- {
- /* Insert a new EXPR_LIST node after ELEM and put the
- new expansion there. */
- new_elem = rtx_alloc (EXPR_LIST);
- XEXP (new_elem, 1) = XEXP (elem, 1);
- XEXP (elem, 1) = new_elem;
- elem = new_elem;
- }
- XEXP (elem, 0) = x;
- }
- }
+ if (iterator->current_value)
+ VEC_safe_push (mapping_ptr, heap, current_iterators, iterator);
return 1;
}
+/* Expand all iterators in the current rtx, which is given as ORIGINAL.
+ Build a list of expanded rtxes in the EXPR_LIST pointed to by QUEUE. */
+
+static void
+apply_iterators (rtx original, rtx *queue)
+{
+ unsigned int i;
+ const char *condition;
+ iterator_use *iuse;
+ struct mapping *iterator;
+ struct map_value *v;
+ rtx x;
+
+ if (VEC_empty (iterator_use, iterator_uses))
+ {
+ /* Raise an error if any attributes were used. */
+ apply_attribute_uses ();
+ XEXP (*queue, 0) = original;
+ XEXP (*queue, 1) = NULL_RTX;
+ return;
+ }
+
+ /* Clear out the iterators from the previous run. */
+ FOR_EACH_VEC_ELT (mapping_ptr, current_iterators, i, iterator)
+ iterator->current_value = NULL;
+ VEC_truncate (mapping_ptr, current_iterators, 0);
+
+ /* Mark the iterators that we need this time. */
+ FOR_EACH_VEC_ELT (iterator_use, iterator_uses, i, iuse)
+ iuse->iterator->current_value = iuse->iterator->values;
+
+ /* Get the list of iterators that are in use, preserving the
+ definition order within each group. */
+ htab_traverse (modes.iterators, add_current_iterators, NULL);
+ htab_traverse (codes.iterators, add_current_iterators, NULL);
+ gcc_assert (!VEC_empty (mapping_ptr, current_iterators));
+
+ for (;;)
+ {
+ /* Apply the current iterator values. Accumulate a condition to
+ say when the resulting rtx can be used. */
+ condition = NULL;
+ FOR_EACH_VEC_ELT (iterator_use, iterator_uses, i, iuse)
+ {
+ v = iuse->iterator->current_value;
+ iuse->iterator->group->apply_iterator (iuse->ptr, v->number);
+ condition = join_c_conditions (condition, v->string);
+ }
+ apply_attribute_uses ();
+ x = copy_rtx_for_iterators (original);
+ add_condition_to_rtx (x, condition);
+
+ /* Add the new rtx to the end of the queue. */
+ XEXP (*queue, 0) = x;
+ XEXP (*queue, 1) = NULL_RTX;
+
+ /* Lexicographically increment the iterator value sequence.
+ That is, cycle through iterator values, starting from the right,
+ and stopping when one of them doesn't wrap around. */
+ i = VEC_length (mapping_ptr, current_iterators);
+ for (;;)
+ {
+ if (i == 0)
+ return;
+ i--;
+ iterator = VEC_index (mapping_ptr, current_iterators, i);
+ iterator->current_value = iterator->current_value->next;
+ if (iterator->current_value)
+ break;
+ iterator->current_value = iterator->values;
+ }
+
+ /* At least one more rtx to go. Allocate room for it. */
+ XEXP (*queue, 1) = rtx_alloc (EXPR_LIST);
+ queue = &XEXP (*queue, 1);
+ }
+}
+
/* Add a new "mapping" structure to hashtable TABLE. NAME is the name
of the mapping and GROUP is the group to which it belongs. */
m = XNEW (struct mapping);
m->name = xstrdup (name);
m->group = group;
- m->index = htab_elements (table);
m->values = 0;
+ m->current_value = NULL;
slot = htab_find_slot (table, m, INSERT);
if (*slot != 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, 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");
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. */
+/* Record that PTR uses iterator ITERATOR. */
-static int
-find_iterator (struct iterator_group *group, const char *name)
+static void
+record_iterator_use (struct mapping *iterator, void *ptr)
+{
+ struct iterator_use *iuse;
+
+ iuse = VEC_safe_push (iterator_use, heap, iterator_uses, NULL);
+ iuse->iterator = iterator;
+ iuse->ptr = ptr;
+}
+
+/* Record that PTR uses attribute VALUE, which must match a built-in
+ value from group GROUP. */
+
+static void
+record_attribute_use (struct iterator_group *group, void *ptr,
+ const char *value)
+{
+ struct attribute_use *ause;
+
+ ause = VEC_safe_push (attribute_use, heap, attribute_uses, NULL);
+ ause->group = group;
+ ause->value = value;
+ ause->ptr = ptr;
+}
+
+/* Interpret NAME as either a built-in value, iterator or attribute
+ for group GROUP. PTR is the value to pass to GROUP's apply_iterator
+ callback. */
+
+static void
+record_potential_iterator_use (struct iterator_group *group, void *ptr,
+ const char *name)
{
struct mapping *m;
+ size_t len;
- m = (struct mapping *) htab_find (group->iterators, &name);
- if (m != 0)
- return m->index + group->num_builtins;
- return group->find_builtin (name);
+ len = strlen (name);
+ if (name[0] == '<' && name[len - 1] == '>')
+ {
+ /* Copy the attribute string into permanent storage, without the
+ angle brackets around it. */
+ obstack_grow0 (&string_obstack, name + 1, len - 2);
+ record_attribute_use (group, ptr, XOBFINISH (&string_obstack, char *));
+ }
+ else
+ {
+ m = (struct mapping *) htab_find (group->iterators, &name);
+ if (m != 0)
+ record_iterator_use (m, ptr);
+ else
+ group->apply_iterator (ptr, group->find_builtin (name));
+ }
}
/* Finish reading a declaration of the form:
}
/* Check newly-created code iterator ITERATOR to see whether every code has the
- same format. Initialize the iterator's entry in bellwether_codes. */
+ same format. */
static void
check_code_iterator (struct mapping *iterator)
if (strcmp (GET_RTX_FORMAT (bellwether), GET_RTX_FORMAT (v->number)) != 0)
fatal_with_file_and_line ("code iterator `%s' combines "
"different rtx formats", iterator->name);
-
- bellwether_codes = XRESIZEVEC (enum rtx_code, bellwether_codes,
- iterator->index + 1);
- bellwether_codes[iterator->index] = bellwether;
}
/* Read an rtx-related declaration from the MD file, given that it
read_rtx (const char *rtx_name, rtx *x)
{
static rtx queue_head;
- struct map_value *mode_maps;
- struct iterator_traverse_data mtd;
/* Do one-time initialization. */
if (queue_head == 0)
return false;
}
- 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);
+ apply_iterators (read_rtx_code (rtx_name), &queue_head);
+ VEC_truncate (iterator_use, iterator_uses, 0);
+ VEC_truncate (attribute_use, attribute_uses, 0);
*x = queue_head;
return true;
/* 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. */
+ return it. */
static rtx
-read_rtx_code (const char *code_name, struct map_value **mode_maps)
+read_rtx_code (const char *code_name)
{
int i;
- RTX_CODE real_code, bellwether_code;
+ RTX_CODE code;
+ struct mapping *iterator;
const char *format_ptr;
struct md_name name;
rtx return_rtx;
rtx value; /* Value of this node. */
};
- real_code = (enum rtx_code) find_iterator (&codes, code_name);
- bellwether_code = BELLWETHER_CODE (real_code);
+ /* If this code is an iterator, build the rtx using the iterator's
+ first value. */
+ iterator = (struct mapping *) htab_find (codes.iterators, &code_name);
+ if (iterator != 0)
+ code = (enum rtx_code) iterator->values->number;
+ else
+ code = (enum rtx_code) codes.find_builtin (code_name);
/* If we end up with an insn expression then we free this space below. */
- return_rtx = rtx_alloc (bellwether_code);
- format_ptr = GET_RTX_FORMAT (bellwether_code);
- PUT_CODE (return_rtx, real_code);
+ return_rtx = rtx_alloc (code);
+ format_ptr = GET_RTX_FORMAT (code);
+ PUT_CODE (return_rtx, code);
+
+ if (iterator)
+ record_iterator_use (iterator, return_rtx);
/* If what follows is `: mode ', read it and
store the mode in the rtx. */
i = read_skip_spaces ();
if (i == ':')
{
- unsigned int mode;
-
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, name.string);
- PUT_MODE (return_rtx, (enum machine_mode) mode);
- if (GET_MODE (return_rtx) != mode)
- fatal_with_file_and_line ("mode too large");
+ record_potential_iterator_use (&modes, return_rtx, name.string);
}
else
unread_char (i);
case 'e':
case 'u':
- XEXP (return_rtx, i) = read_nested_rtx (mode_maps);
+ XEXP (return_rtx, i) = read_nested_rtx ();
break;
case 'V':
fatal_expected_char (']', c);
unread_char (c);
list_counter++;
- obstack_ptr_grow (&vector_stack, read_nested_rtx (mode_maps));
+ obstack_ptr_grow (&vector_stack, read_nested_rtx ());
}
if (list_counter > 0)
{
if (c == '('
&& (GET_CODE (return_rtx) == AND
|| GET_CODE (return_rtx) == IOR))
- return read_rtx_variadic (mode_maps, return_rtx);
+ return read_rtx_variadic (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. */
+/* Read a nested rtx construct from the MD file and return it. */
static rtx
-read_nested_rtx (struct map_value **mode_maps)
+read_nested_rtx (void)
{
struct md_name name;
int c;
if (strcmp (name.string, "nil") == 0)
return_rtx = NULL;
else
- return_rtx = read_rtx_code (name.string, mode_maps);
+ return_rtx = read_rtx_code (name.string);
c = read_skip_spaces ();
if (c != ')')
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 (struct map_value **mode_maps, rtx form)
+read_rtx_variadic (rtx form)
{
char c = '(';
rtx p = form, q;
PUT_MODE (q, GET_MODE (p));
XEXP (q, 0) = XEXP (p, 1);
- XEXP (q, 1) = read_nested_rtx (mode_maps);
+ XEXP (q, 1) = read_nested_rtx ();
XEXP (p, 1) = q;
p = q;