diff options
Diffstat (limited to 'gcc/read-rtl.c')
-rw-r--r-- | gcc/read-rtl.c | 198 |
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) { |