aboutsummaryrefslogtreecommitdiff
path: root/gcc/read-rtl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/read-rtl.c')
-rw-r--r--gcc/read-rtl.c198
1 files changed, 160 insertions, 38 deletions
diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c
index b9e0cb5..23db85b 100644
--- a/gcc/read-rtl.c
+++ b/gcc/read-rtl.c
@@ -87,6 +87,17 @@ struct ptr_loc {
int lineno;
};
+/* A structure used to pass data from read_rtx to apply_macro_traverse
+ via htab_traverse. */
+struct macro_traverse_data {
+ /* Instruction queue. */
+ rtx queue;
+ /* Attributes seen for modes. */
+ struct map_value *mode_maps;
+ /* Input file. */
+ FILE *infile;
+};
+
/* If CODE is the number of a code macro, return a real rtx code that
has the same format. Return CODE otherwise. */
#define BELLWETHER_CODE(CODE) \
@@ -102,7 +113,8 @@ 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);
+static rtx apply_macro_to_rtx (rtx, struct mapping *, int,
+ struct map_value *, FILE *);
static bool uses_macro_p (rtx, struct mapping *);
static const char *add_condition_to_string (const char *, const char *);
static void add_condition_to_rtx (rtx, const char *);
@@ -128,7 +140,7 @@ 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 *);
+static rtx read_rtx_1 (FILE *, struct map_value **);
/* The mode and code macro structures. */
static struct macro_group modes, codes;
@@ -258,6 +270,115 @@ apply_code_macro (rtx x, int code)
PUT_CODE (x, code);
}
+/* Map a code or mode attribute string P to the underlying string for
+ MACRO and VALUE. */
+
+static struct map_value *
+map_attr_string (const char *p, struct mapping *macro, int value)
+{
+ const char *attr;
+ struct mapping *m;
+ struct map_value *v;
+
+ /* If there's a "macro:" prefix, check whether the macro 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)
+ return 0;
+ attr++;
+ }
+
+ /* Find the attribute specification. */
+ m = (struct mapping *) htab_find (macro->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_macro_to_rtx. */
+
+static unsigned int
+mode_attr_index (struct map_value **mode_maps, const char *string,
+ FILE *infile)
+{
+ char *p;
+ char *attr;
+ struct map_value *mv;
+
+ /* Copy the attribute string into permanent storage, without the
+ angle brackets around it. */
+ obstack_grow (&string_obstack, string + 1, strlen (string) - 2);
+ p = (char *) obstack_finish (&string_obstack);
+
+ /* Make sure the attribute is defined as either a code attribute or
+ a mode attribute. */
+ attr = strchr (p, ':');
+ if (attr == 0)
+ attr = p;
+ else
+ ++attr;
+
+ if (!htab_find (modes.attrs, &attr) && !htab_find (codes.attrs, &attr))
+ fatal_with_file_and_line (infile,
+ "undefined attribute '%s' used for mode",
+ p);
+
+ 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 macros + the index
+ we just used. */
+ return MAX_MACHINE_MODE + htab_elements (modes.macros) + mv->number;
+}
+
+/* Apply MODE_MAPS to the top level of X. */
+
+static void
+apply_mode_maps (rtx x, struct map_value *mode_maps, struct mapping *macro,
+ int value, FILE *infile)
+{
+ unsigned int offset;
+ int indx;
+ struct map_value *pm;
+
+ offset = MAX_MACHINE_MODE + htab_elements (modes.macros);
+ if (GET_MODE (x) < offset)
+ return;
+
+ indx = GET_MODE (x) - offset;
+ for (pm = mode_maps; pm; pm = pm->next)
+ {
+ if (pm->number == indx)
+ {
+ struct map_value *v;
+
+ v = map_attr_string (pm->string, macro, value);
+ if (v)
+ {
+ PUT_MODE (x, find_mode (v->string, infile));
+ return;
+ }
+ }
+ }
+}
+
/* Given that MACRO 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. */
@@ -265,8 +386,7 @@ apply_code_macro (rtx x, int code)
static const char *
apply_macro_to_string (const char *string, struct mapping *macro, int value)
{
- char *base, *copy, *p, *attr, *start, *end;
- struct mapping *m;
+ char *base, *copy, *p, *start, *end;
struct map_value *v;
if (string == 0)
@@ -277,30 +397,9 @@ apply_macro_to_string (const char *string, struct mapping *macro, int value)
{
p = start + 1;
- /* If there's a "macro:" prefix, check whether the macro name matches.
- Set ATTR to the start of the attribute name. */
- attr = strchr (p, ':');
- if (attr == 0 || attr > end)
- attr = p;
- else
- {
- if (strncmp (p, macro->name, attr - p) != 0
- || macro->name[attr - p] != 0)
- continue;
- attr++;
- }
-
- /* Find the attribute specification. */
*end = 0;
- m = (struct mapping *) htab_find (macro->group->attrs, &attr);
+ v = map_attr_string (p, macro, value);
*end = '>';
- if (m == 0)
- continue;
-
- /* Find the attribute value for VALUE. */
- for (v = m->values; v != 0; v = v->next)
- if (v->number == value)
- break;
if (v == 0)
continue;
@@ -324,7 +423,8 @@ apply_macro_to_string (const char *string, struct mapping *macro, int value)
replaced by VALUE. */
static rtx
-apply_macro_to_rtx (rtx original, struct mapping *macro, int value)
+apply_macro_to_rtx (rtx original, struct mapping *macro, int value,
+ struct map_value *mode_maps, FILE *infile)
{
struct macro_group *group;
const char *format_ptr;
@@ -345,6 +445,9 @@ apply_macro_to_rtx (rtx original, struct mapping *macro, int value)
if (group->uses_macro_p (x, macro->index + group->num_builtins))
group->apply_macro (x, value);
+ if (mode_maps)
+ apply_mode_maps (x, mode_maps, macro, value, infile);
+
/* Change each string and recursively change each rtx. */
format_ptr = GET_RTX_FORMAT (bellwether_code);
for (i = 0; format_ptr[i] != 0; i++)
@@ -360,7 +463,8 @@ apply_macro_to_rtx (rtx original, struct mapping *macro, int value)
break;
case 'e':
- XEXP (x, i) = apply_macro_to_rtx (XEXP (x, i), macro, value);
+ XEXP (x, i) = apply_macro_to_rtx (XEXP (x, i), macro, value,
+ mode_maps, infile);
break;
case 'V':
@@ -370,7 +474,8 @@ 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);
+ macro, value, mode_maps,
+ infile);
}
break;
@@ -467,18 +572,20 @@ add_condition_to_rtx (rtx x, const char *extra)
static int
apply_macro_traverse (void **slot, void *data)
{
+ struct macro_traverse_data *mtd = (struct macro_traverse_data *) data;
struct mapping *macro;
struct map_value *v;
rtx elem, new_elem, original, x;
macro = (struct mapping *) *slot;
- for (elem = (rtx) data; elem != 0; elem = XEXP (elem, 1))
+ for (elem = mtd->queue; elem != 0; elem = XEXP (elem, 1))
if (uses_macro_p (XEXP (elem, 0), macro))
{
original = XEXP (elem, 0);
for (v = macro->values; v != 0; v = v->next)
{
- x = apply_macro_to_rtx (original, macro, v->number);
+ x = apply_macro_to_rtx (original, macro, v->number,
+ mtd->mode_maps, mtd->infile);
add_condition_to_rtx (x, v->string);
if (v != macro->values)
{
@@ -1238,6 +1345,9 @@ read_rtx (FILE *infile, rtx *x, int *lineno)
if (queue_next == 0)
{
+ struct map_value *mode_maps;
+ struct macro_traverse_data mtd;
+
c = read_skip_spaces (infile);
if (c == EOF)
return false;
@@ -1245,11 +1355,15 @@ read_rtx (FILE *infile, rtx *x, int *lineno)
queue_next = queue_head;
queue_lineno = read_rtx_lineno;
- XEXP (queue_next, 0) = read_rtx_1 (infile);
+ mode_maps = 0;
+ XEXP (queue_next, 0) = read_rtx_1 (infile, &mode_maps);
XEXP (queue_next, 1) = 0;
- htab_traverse (modes.macros, apply_macro_traverse, queue_next);
- htab_traverse (codes.macros, apply_macro_traverse, queue_next);
+ mtd.queue = queue_next;
+ mtd.mode_maps = mode_maps;
+ mtd.infile = infile;
+ htab_traverse (modes.macros, apply_macro_traverse, &mtd);
+ htab_traverse (codes.macros, apply_macro_traverse, &mtd);
}
*x = XEXP (queue_next, 0);
@@ -1263,7 +1377,7 @@ read_rtx (FILE *infile, rtx *x, int *lineno)
doesn't apply any macros. */
static rtx
-read_rtx_1 (FILE *infile)
+read_rtx_1 (FILE *infile, struct map_value **mode_maps)
{
int i;
RTX_CODE real_code, bellwether_code;
@@ -1337,8 +1451,16 @@ read_rtx_1 (FILE *infile)
i = read_skip_spaces (infile);
if (i == ':')
{
+ unsigned int mode;
+
read_name (tmp_char, infile);
- PUT_MODE (return_rtx, find_macro (&modes, tmp_char, infile));
+ if (tmp_char[0] != '<' || tmp_char[strlen (tmp_char) - 1] != '>')
+ mode = find_macro (&modes, tmp_char, infile);
+ else
+ mode = mode_attr_index (mode_maps, tmp_char, infile);
+ PUT_MODE (return_rtx, mode);
+ if (GET_MODE (return_rtx) != mode)
+ fatal_with_file_and_line (infile, "mode too large");
}
else
ungetc (i, infile);
@@ -1353,7 +1475,7 @@ read_rtx_1 (FILE *infile)
case 'e':
case 'u':
- XEXP (return_rtx, i) = read_rtx_1 (infile);
+ XEXP (return_rtx, i) = read_rtx_1 (infile, mode_maps);
break;
case 'V':
@@ -1385,7 +1507,7 @@ read_rtx_1 (FILE *infile)
{
ungetc (c, infile);
list_counter++;
- obstack_ptr_grow (&vector_stack, read_rtx_1 (infile));
+ obstack_ptr_grow (&vector_stack, read_rtx_1 (infile, mode_maps));
}
if (list_counter > 0)
{