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
This commit is contained in:
parent
5deaef19e6
commit
f30990b2ee
3 changed files with 204 additions and 49 deletions
|
@ -1,3 +1,21 @@
|
|||
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>
|
||||
|
||||
* tree-cfg.c (tree_duplicate_sese_region): Update profile.
|
||||
|
|
|
@ -6718,7 +6718,7 @@ rtx-based construct, such as a @code{define_insn},
|
|||
|
||||
@menu
|
||||
* Defining Mode Macros:: Defining a new mode macro.
|
||||
* String Substitutions:: Combining mode macros with string substitutions
|
||||
* Substitutions:: Combining mode macros with substitutions
|
||||
* Examples:: Examples
|
||||
@end menu
|
||||
|
||||
|
@ -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
|
||||
significant if two macros are used in a construct that requires
|
||||
string substitutions. @xref{String Substitutions}.
|
||||
substitutions. @xref{Substitutions}.
|
||||
|
||||
@node String Substitutions
|
||||
@subsubsection String Substitution in Mode Macros
|
||||
@node Substitutions
|
||||
@subsubsection Substitution in Mode Macros
|
||||
@findex define_mode_attr
|
||||
|
||||
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
|
||||
@item
|
||||
|
@ -6782,6 +6783,11 @@ appropriate mode name for @var{m}.
|
|||
@item
|
||||
When a @code{define_insn} defines several instruction patterns,
|
||||
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
|
||||
|
||||
GCC supports such variations through a system of ``mode attributes''.
|
||||
|
@ -6796,12 +6802,12 @@ upper case. You can define other attributes using:
|
|||
where @var{name} is the name of the attribute and @var{valuei}
|
||||
is the value associated with @var{modei}.
|
||||
|
||||
When GCC replaces some @var{:macro} with @var{:mode}, it will
|
||||
scan each string in the pattern for sequences of the form
|
||||
@code{<@var{macro}:@var{attr}>}, where @var{attr} is the name of
|
||||
a mode attribute. If the attribute is defined for @var{mode}, the
|
||||
whole @code{<...>} sequence will be replaced by the appropriate
|
||||
attribute value.
|
||||
When GCC replaces some @var{:macro} with @var{:mode}, it will scan
|
||||
each string and mode in the pattern for sequences of the form
|
||||
@code{<@var{macro}:@var{attr}>}, where @var{attr} is the name of a
|
||||
mode attribute. If the attribute is defined for @var{mode}, the whole
|
||||
@code{<...>} sequence will be replaced by the appropriate attribute
|
||||
value.
|
||||
|
||||
For example, suppose an @file{.md} file has:
|
||||
|
||||
|
@ -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
|
||||
@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
|
||||
substitution will be attempted for every macro expansion.
|
||||
|
||||
|
|
198
gcc/read-rtl.c
198
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)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue