Commit f30990b2 by Ian Lance Taylor Committed by Ian Lance Taylor

read-rtl.c (struct macro_traverse_data): Define.

	* read-rtl.c (struct macro_traverse_data): Define.
	(map_attr_string): New static function, broken out of
	apply_macro_to_string.
	(mode_attr_index, apply_mode_maps): New static functions.
	(apply_macro_to_string): Call map_attr_string.
	(apply_macro_to_rtx): Add mode_maps and infile parameters.  Change
	all callers.
	(apply_macro_traverse): Expect data to point to a struct
	macro_traverse_data.
	(read_rtx): Add mode_maps local variable.  Use mode_traverse_data
	to pass data through htab_traverse.
	(read_rtx_1): Add mode_maps parameter.  Change all callers.
	Handle mode names which are attribute strings.
	* doc/md.texi (Substitutions): Rename from String Substitutions.
	Change references.  Document using attributes as modes.

From-SVN: r99548
parent 5deaef19
2005-05-10 Ian Lance Taylor <ian@airs.com>
* read-rtl.c (struct macro_traverse_data): Define.
(map_attr_string): New static function, broken out of
apply_macro_to_string.
(mode_attr_index, apply_mode_maps): New static functions.
(apply_macro_to_string): Call map_attr_string.
(apply_macro_to_rtx): Add mode_maps and infile parameters. Change
all callers.
(apply_macro_traverse): Expect data to point to a struct
macro_traverse_data.
(read_rtx): Add mode_maps local variable. Use mode_traverse_data
to pass data through htab_traverse.
(read_rtx_1): Add mode_maps parameter. Change all callers.
Handle mode names which are attribute strings.
* doc/md.texi (Substitutions): Rename from String Substitutions.
Change references. Document using attributes as modes.
2005-05-10 Zdenek Dvorak <dvorakz@suse.cz> 2005-05-10 Zdenek Dvorak <dvorakz@suse.cz>
* tree-cfg.c (tree_duplicate_sese_region): Update profile. * tree-cfg.c (tree_duplicate_sese_region): Update profile.
......
...@@ -6718,7 +6718,7 @@ rtx-based construct, such as a @code{define_insn}, ...@@ -6718,7 +6718,7 @@ rtx-based construct, such as a @code{define_insn},
@menu @menu
* Defining Mode Macros:: Defining a new mode macro. * Defining Mode Macros:: Defining a new mode macro.
* String Substitutions:: Combining mode macros with string substitutions * Substitutions:: Combining mode macros with substitutions
* Examples:: Examples * Examples:: Examples
@end menu @end menu
...@@ -6764,14 +6764,15 @@ but that the @code{:SI} expansion has no such constraint. ...@@ -6764,14 +6764,15 @@ but that the @code{:SI} expansion has no such constraint.
Macros are applied in the order they are defined. This can be Macros are applied in the order they are defined. This can be
significant if two macros are used in a construct that requires significant if two macros are used in a construct that requires
string substitutions. @xref{String Substitutions}. substitutions. @xref{Substitutions}.
@node String Substitutions @node Substitutions
@subsubsection String Substitution in Mode Macros @subsubsection Substitution in Mode Macros
@findex define_mode_attr @findex define_mode_attr
If an @file{.md} file construct uses mode macros, each version of the If an @file{.md} file construct uses mode macros, each version of the
construct will often need slightly different strings. For example: construct will often need slightly different strings or modes. For
example:
@itemize @bullet @itemize @bullet
@item @item
...@@ -6782,6 +6783,11 @@ appropriate mode name for @var{m}. ...@@ -6782,6 +6783,11 @@ appropriate mode name for @var{m}.
@item @item
When a @code{define_insn} defines several instruction patterns, When a @code{define_insn} defines several instruction patterns,
each instruction will often use a different assembler mnemonic. each instruction will often use a different assembler mnemonic.
@item
When a @code{define_insn} requires operands with different modes,
using a macro for one of the operand modes usually requires a specific
mode for the other operand(s).
@end itemize @end itemize
GCC supports such variations through a system of ``mode attributes''. GCC supports such variations through a system of ``mode attributes''.
...@@ -6796,12 +6802,12 @@ upper case. You can define other attributes using: ...@@ -6796,12 +6802,12 @@ upper case. You can define other attributes using:
where @var{name} is the name of the attribute and @var{valuei} where @var{name} is the name of the attribute and @var{valuei}
is the value associated with @var{modei}. is the value associated with @var{modei}.
When GCC replaces some @var{:macro} with @var{:mode}, it will When GCC replaces some @var{:macro} with @var{:mode}, it will scan
scan each string in the pattern for sequences of the form each string and mode in the pattern for sequences of the form
@code{<@var{macro}:@var{attr}>}, where @var{attr} is the name of @code{<@var{macro}:@var{attr}>}, where @var{attr} is the name of a
a mode attribute. If the attribute is defined for @var{mode}, the mode attribute. If the attribute is defined for @var{mode}, the whole
whole @code{<...>} sequence will be replaced by the appropriate @code{<...>} sequence will be replaced by the appropriate attribute
attribute value. value.
For example, suppose an @file{.md} file has: For example, suppose an @file{.md} file has:
...@@ -6815,6 +6821,15 @@ If one of the patterns that uses @code{:P} contains the string ...@@ -6815,6 +6821,15 @@ If one of the patterns that uses @code{:P} contains the string
will use @code{"lw\t%0,%1"} and the @code{DI} version will use will use @code{"lw\t%0,%1"} and the @code{DI} version will use
@code{"ld\t%0,%1"}. @code{"ld\t%0,%1"}.
Here is an example of using an attribute for a mode:
@smallexample
(define_mode_macro LONG [SI DI])
(define_mode_attr SHORT [(SI "HI") (DI "SI")])
(define_insn ...
(sign_extend:LONG (match_operand:<LONG:SHORT> ...)) ...)
@end smallexample
The @code{@var{macro}:} prefix may be omitted, in which case the The @code{@var{macro}:} prefix may be omitted, in which case the
substitution will be attempted for every macro expansion. substitution will be attempted for every macro expansion.
......
...@@ -87,6 +87,17 @@ struct ptr_loc { ...@@ -87,6 +87,17 @@ struct ptr_loc {
int lineno; 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 /* If CODE is the number of a code macro, return a real rtx code that
has the same format. Return CODE otherwise. */ has the same format. Return CODE otherwise. */
#define BELLWETHER_CODE(CODE) \ #define BELLWETHER_CODE(CODE) \
...@@ -102,7 +113,8 @@ static int find_code (const char *, FILE *); ...@@ -102,7 +113,8 @@ static int find_code (const char *, FILE *);
static bool uses_code_macro_p (rtx, int); static bool uses_code_macro_p (rtx, int);
static void apply_code_macro (rtx, int); static void apply_code_macro (rtx, int);
static const char *apply_macro_to_string (const char *, struct mapping *, 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 bool uses_macro_p (rtx, struct mapping *);
static const char *add_condition_to_string (const char *, const char *); static const char *add_condition_to_string (const char *, const char *);
static void add_condition_to_rtx (rtx, const char *); static void add_condition_to_rtx (rtx, const char *);
...@@ -128,7 +140,7 @@ static void validate_const_int (FILE *, 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 int find_macro (struct macro_group *, const char *, FILE *);
static struct mapping *read_mapping (struct macro_group *, htab_t, FILE *); static struct mapping *read_mapping (struct macro_group *, htab_t, FILE *);
static void check_code_macro (struct mapping *, 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. */ /* The mode and code macro structures. */
static struct macro_group modes, codes; static struct macro_group modes, codes;
...@@ -258,49 +270,136 @@ apply_code_macro (rtx x, int code) ...@@ -258,49 +270,136 @@ apply_code_macro (rtx x, int code)
PUT_CODE (x, code); PUT_CODE (x, code);
} }
/* Given that MACRO is being expanded as VALUE, apply the appropriate /* Map a code or mode attribute string P to the underlying string for
string substitutions to STRING. Return the new string if any changes MACRO and VALUE. */
were needed, otherwise return STRING itself. */
static const char * static struct map_value *
apply_macro_to_string (const char *string, struct mapping *macro, int value) map_attr_string (const char *p, struct mapping *macro, int value)
{ {
char *base, *copy, *p, *attr, *start, *end; const char *attr;
struct mapping *m; struct mapping *m;
struct map_value *v; struct map_value *v;
if (string == 0)
return string;
base = p = copy = ASTRDUP (string);
while ((start = strchr (p, '<')) && (end = strchr (start, '>')))
{
p = start + 1;
/* If there's a "macro:" prefix, check whether the macro name matches. /* If there's a "macro:" prefix, check whether the macro name matches.
Set ATTR to the start of the attribute name. */ Set ATTR to the start of the attribute name. */
attr = strchr (p, ':'); attr = strchr (p, ':');
if (attr == 0 || attr > end) if (attr == 0)
attr = p; attr = p;
else else
{ {
if (strncmp (p, macro->name, attr - p) != 0 if (strncmp (p, macro->name, attr - p) != 0
|| macro->name[attr - p] != 0) || macro->name[attr - p] != 0)
continue; return 0;
attr++; attr++;
} }
/* Find the attribute specification. */ /* Find the attribute specification. */
*end = 0;
m = (struct mapping *) htab_find (macro->group->attrs, &attr); m = (struct mapping *) htab_find (macro->group->attrs, &attr);
*end = '>';
if (m == 0) if (m == 0)
continue; return 0;
/* Find the attribute value for VALUE. */ /* Find the attribute value for VALUE. */
for (v = m->values; v != 0; v = v->next) for (v = m->values; v != 0; v = v->next)
if (v->number == value) if (v->number == value)
break; 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. */
static const char *
apply_macro_to_string (const char *string, struct mapping *macro, int value)
{
char *base, *copy, *p, *start, *end;
struct map_value *v;
if (string == 0)
return string;
base = p = copy = ASTRDUP (string);
while ((start = strchr (p, '<')) && (end = strchr (start, '>')))
{
p = start + 1;
*end = 0;
v = map_attr_string (p, macro, value);
*end = '>';
if (v == 0) if (v == 0)
continue; continue;
...@@ -324,7 +423,8 @@ apply_macro_to_string (const char *string, struct mapping *macro, int value) ...@@ -324,7 +423,8 @@ apply_macro_to_string (const char *string, struct mapping *macro, int value)
replaced by VALUE. */ replaced by VALUE. */
static rtx 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; struct macro_group *group;
const char *format_ptr; const char *format_ptr;
...@@ -345,6 +445,9 @@ apply_macro_to_rtx (rtx original, struct mapping *macro, int value) ...@@ -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)) if (group->uses_macro_p (x, macro->index + group->num_builtins))
group->apply_macro (x, value); 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. */ /* Change each string and recursively change each rtx. */
format_ptr = GET_RTX_FORMAT (bellwether_code); format_ptr = GET_RTX_FORMAT (bellwether_code);
for (i = 0; format_ptr[i] != 0; i++) for (i = 0; format_ptr[i] != 0; i++)
...@@ -360,7 +463,8 @@ apply_macro_to_rtx (rtx original, struct mapping *macro, int value) ...@@ -360,7 +463,8 @@ apply_macro_to_rtx (rtx original, struct mapping *macro, int value)
break; break;
case 'e': 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; break;
case 'V': case 'V':
...@@ -370,7 +474,8 @@ apply_macro_to_rtx (rtx original, struct mapping *macro, int value) ...@@ -370,7 +474,8 @@ apply_macro_to_rtx (rtx original, struct mapping *macro, int value)
XVEC (x, i) = rtvec_alloc (XVECLEN (original, i)); XVEC (x, i) = rtvec_alloc (XVECLEN (original, i));
for (j = 0; j < XVECLEN (x, i); j++) for (j = 0; j < XVECLEN (x, i); j++)
XVECEXP (x, i, j) = apply_macro_to_rtx (XVECEXP (original, i, j), XVECEXP (x, i, j) = apply_macro_to_rtx (XVECEXP (original, i, j),
macro, value); macro, value, mode_maps,
infile);
} }
break; break;
...@@ -467,18 +572,20 @@ add_condition_to_rtx (rtx x, const char *extra) ...@@ -467,18 +572,20 @@ add_condition_to_rtx (rtx x, const char *extra)
static int static int
apply_macro_traverse (void **slot, void *data) apply_macro_traverse (void **slot, void *data)
{ {
struct macro_traverse_data *mtd = (struct macro_traverse_data *) data;
struct mapping *macro; struct mapping *macro;
struct map_value *v; struct map_value *v;
rtx elem, new_elem, original, x; rtx elem, new_elem, original, x;
macro = (struct mapping *) *slot; 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)) if (uses_macro_p (XEXP (elem, 0), macro))
{ {
original = XEXP (elem, 0); original = XEXP (elem, 0);
for (v = macro->values; v != 0; v = v->next) 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); add_condition_to_rtx (x, v->string);
if (v != macro->values) if (v != macro->values)
{ {
...@@ -1238,6 +1345,9 @@ read_rtx (FILE *infile, rtx *x, int *lineno) ...@@ -1238,6 +1345,9 @@ read_rtx (FILE *infile, rtx *x, int *lineno)
if (queue_next == 0) if (queue_next == 0)
{ {
struct map_value *mode_maps;
struct macro_traverse_data mtd;
c = read_skip_spaces (infile); c = read_skip_spaces (infile);
if (c == EOF) if (c == EOF)
return false; return false;
...@@ -1245,11 +1355,15 @@ read_rtx (FILE *infile, rtx *x, int *lineno) ...@@ -1245,11 +1355,15 @@ read_rtx (FILE *infile, rtx *x, int *lineno)
queue_next = queue_head; queue_next = queue_head;
queue_lineno = read_rtx_lineno; 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; XEXP (queue_next, 1) = 0;
htab_traverse (modes.macros, apply_macro_traverse, queue_next); mtd.queue = queue_next;
htab_traverse (codes.macros, apply_macro_traverse, 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); *x = XEXP (queue_next, 0);
...@@ -1263,7 +1377,7 @@ read_rtx (FILE *infile, rtx *x, int *lineno) ...@@ -1263,7 +1377,7 @@ read_rtx (FILE *infile, rtx *x, int *lineno)
doesn't apply any macros. */ doesn't apply any macros. */
static rtx static rtx
read_rtx_1 (FILE *infile) read_rtx_1 (FILE *infile, struct map_value **mode_maps)
{ {
int i; int i;
RTX_CODE real_code, bellwether_code; RTX_CODE real_code, bellwether_code;
...@@ -1337,8 +1451,16 @@ read_rtx_1 (FILE *infile) ...@@ -1337,8 +1451,16 @@ read_rtx_1 (FILE *infile)
i = read_skip_spaces (infile); i = read_skip_spaces (infile);
if (i == ':') if (i == ':')
{ {
unsigned int mode;
read_name (tmp_char, infile); 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 else
ungetc (i, infile); ungetc (i, infile);
...@@ -1353,7 +1475,7 @@ read_rtx_1 (FILE *infile) ...@@ -1353,7 +1475,7 @@ read_rtx_1 (FILE *infile)
case 'e': case 'e':
case 'u': case 'u':
XEXP (return_rtx, i) = read_rtx_1 (infile); XEXP (return_rtx, i) = read_rtx_1 (infile, mode_maps);
break; break;
case 'V': case 'V':
...@@ -1385,7 +1507,7 @@ read_rtx_1 (FILE *infile) ...@@ -1385,7 +1507,7 @@ read_rtx_1 (FILE *infile)
{ {
ungetc (c, infile); ungetc (c, infile);
list_counter++; 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) if (list_counter > 0)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment