Commit 84b72302 by Richard Henderson Committed by Richard Henderson

c-parse.in (asm_operand): Allow named operands.

        * c-parse.in (asm_operand): Allow named operands.
        * genconfig.c (max_recog_operands): Set to 29.
        * local-alloc.c (requires_inout): Skip multiple digits.
        * recog.c (asm_operand_ok): Likewise.
        (preprocess_constraints): Use strtoul for matching constraints.
        (constrain_operands): Likewise.
        * regmove.c (find_matches): Likewise.
        * reload.c (find_reloads): Likewise.
        * stmt.c (parse_output_constraint): Don't reject in-out
        constraint on operands > 9.  Reject '[' in constraint.
        (expand_asm_operands): Handle named operands.  Use strtoul
        for matching constraints.
        (check_operand_nalternatives): Split out from expand_asm_operands.
        (check_unique_operand_names): New.
        (resolve_operand_names, resolve_operand_name_1): New.

        * doc/extend.texi (Extended Asm): Document named operands.
        * doc/md.texi (Simple Constraints): Document matching constraints
        on operands > 9.

        * parse.y (asm_operand): Allow named operands.
        * semantics.c (finish_asm_stmt): Tweek for changed location
        of the operand constrant.

From-SVN: r46179
parent 592188a5
2001-10-10 Richard Henderson <rth@redhat.com>
* c-parse.in (asm_operand): Allow named operands.
* genconfig.c (max_recog_operands): Set to 29.
* local-alloc.c (requires_inout): Skip multiple digits.
* recog.c (asm_operand_ok): Likewise.
(preprocess_constraints): Use strtoul for matching constraints.
(constrain_operands): Likewise.
* regmove.c (find_matches): Likewise.
* reload.c (find_reloads): Likewise.
* stmt.c (parse_output_constraint): Don't reject in-out
constraint on operands > 9. Reject '[' in constraint.
(expand_asm_operands): Handle named operands. Use strtoul
for matching constraints.
(check_operand_nalternatives): Split out from expand_asm_operands.
(check_unique_operand_names): New.
(resolve_operand_names, resolve_operand_name_1): New.
* doc/extend.texi (Extended Asm): Document named operands.
* doc/md.texi (Simple Constraints): Document matching constraints
on operands > 9.
2001-10-10 Richard Henderson <rth@redhat.com>
* combine.c (try_combine): Handle a SEQUENCE of one insn.
* i386.c (test splitter): Narrow tests vs paradoxical subregs.
......
......@@ -2454,7 +2454,9 @@ nonnull_asm_operands:
asm_operand:
STRING '(' expr ')'
{ $$ = build_tree_list ($1, $3); }
{ $$ = build_tree_list (build_tree_list (NULL_TREE, $1), $3); }
| '[' identifier ']' STRING '(' expr ')'
{ $$ = build_tree_list (build_tree_list ($2, $4), $6); }
;
asm_clobbers:
......
2001-10-10 Richard Henderson <rth@redhat.com>
* parse.y (asm_operand): Allow named operands.
* semantics.c (finish_asm_stmt): Tweek for changed location
of the operand constrant.
2001-10-09 Jason Merrill <jason_merrill@redhat.com>
* call.c (standard_conversion): Add bad conversion between
......
......@@ -3607,7 +3607,9 @@ nonnull_asm_operands:
asm_operand:
STRING '(' expr ')'
{ $$ = build_tree_list ($$, $3); }
{ $$ = build_tree_list (build_tree_list (NULL_TREE, $1), $3); }
| '[' identifier ']' STRING '(' expr ')'
{ $$ = build_tree_list (build_tree_list ($2, $4), $6); }
;
asm_clobbers:
......
......@@ -929,7 +929,7 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
const char *constraint;
tree operand;
constraint = TREE_STRING_POINTER (TREE_PURPOSE (t));
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
operand = TREE_VALUE (output_operands);
if (!parse_output_constraint (&constraint,
......
......@@ -3382,14 +3382,34 @@ Each operand is described by an operand-constraint string followed by
the C expression in parentheses. A colon separates the assembler
template from the first output operand and another separates the last
output operand from the first input, if any. Commas separate the
operands within each group. The total number of operands is limited to
ten or to the maximum number of operands in any instruction pattern in
the machine description, whichever is greater.
operands within each group. The total number of operands is currently
limited to 30; this limitation may be lifted in some future version of
GCC.
If there are no output operands but there are input operands, you must
place two consecutive colons surrounding the place where the output
operands would go.
As of GCC version 3.1, it is also possible to specify input and output
operands using symbolic names which can be referenced within the
assembler code. These names are specified inside square brackets
preceding the constraint string, and can be referenced inside the
assembler code using @code{%[@var{name}]} instead of a percentage sign
followed by the operand number. Using named operands the above example
could look like:
@example
asm ("fsinx %[angle],%[output]"
: [output] "=f" (result)
: [angle] "f" (angle));
@end example
@noindent
Note that the symbolic operand names have no relation whatsoever to
other C identifiers. You may use any name you like, even those of
existing C symbols, but must ensure that no two operands within the same
assembler construct use the same symbolic name.
Output operand expressions must be lvalues; the compiler can check this.
The input operands need not be lvalues. The compiler cannot check
whether the operands have data types that are reasonable for the
......@@ -3425,10 +3445,10 @@ asm ("combine %2,%0" : "=r" (foo) : "0" (foo), "g" (bar));
@noindent
The constraint @samp{"0"} for operand 1 says that it must occupy the
same location as operand 0. A digit in constraint is allowed only in an
input operand and it must refer to an output operand.
same location as operand 0. A number in constraint is allowed only in
an input operand and it must refer to an output operand.
Only a digit in the constraint can guarantee that one operand will be in
Only a number in the constraint can guarantee that one operand will be in
the same place as another. The mere fact that @code{foo} is the value
of both operands is not enough to guarantee that they will be in the
same place in the generated assembler code. The following would not
......@@ -3446,6 +3466,15 @@ register (copying it afterward to @code{foo}'s own address). Of course,
since the register for operand 1 is not even mentioned in the assembler
code, the result will not work, but GCC can't tell that.
As of GCC version 3.1, one may write @code{[@var{name}]} instead of
the operand number for a matching constraint. For example:
@example
asm ("cmoveq %1,%2,%[result]"
: [result] "=r"(result)
: "r" (test), "r"(new), "[result]"(old));
@end example
Some instructions clobber specific hard registers. To describe this,
write a third colon after the input operands, followed by the names of
the clobbered hard registers (given as strings). Here is a realistic
......
......@@ -894,6 +894,13 @@ An operand that matches the specified operand number is allowed. If a
digit is used together with letters within the same alternative, the
digit should come last.
This number is allowed to be more than a single digit. If multiple
digits are encountered consecutavely, they are interpreted as a single
decimal integer. There is scant chance for ambiguity, since to-date
it has never been desirable that @samp{10} be interpreted as matching
either operand 1 @emph{or} operand 0. Should this be desired, one
can use multiple alternatives instead.
@cindex matching constraint
@cindex constraint, matching
This is called a @dfn{matching constraint} and what it really means is
......
......@@ -285,8 +285,10 @@ main (argc, argv)
puts ("#ifndef GCC_INSN_CONFIG_H");
puts ("#define GCC_INSN_CONFIG_H\n");
/* Allow at least 10 operands for the sake of asm constructs. */
max_recog_operands = 9; /* We will add 1 later. */
/* Allow at least 30 operands for the sake of asm constructs. */
/* ??? We *really* ought to reorganize things such that there
is no fixed upper bound. */
max_recog_operands = 29; /* We will add 1 later. */
max_dup_operands = 1;
/* Read the machine description. */
......
......@@ -1302,7 +1302,7 @@ block_alloc (b)
for (i = 1; i < recog_data.n_operands; i++)
{
const char *p = recog_data.constraints[i];
int this_match = (requires_inout (p));
int this_match = requires_inout (p);
n_matching_alts += this_match;
if (this_match == recog_data.n_alternatives)
......@@ -2409,8 +2409,6 @@ requires_inout (p)
case '=': case '+': case '?':
case '#': case '&': case '!':
case '*': case '%':
case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
case 'm': case '<': case '>': case 'V': case 'o':
case 'E': case 'F': case 'G': case 'H':
case 's': case 'i': case 'n':
......@@ -2431,6 +2429,13 @@ requires_inout (p)
found_zero = 1;
break;
case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
/* Skip the balance of the matching constraint. */
while (*p >= '0' && *p <= '9')
p++;
break;
default:
if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
break;
......
......@@ -1657,6 +1657,8 @@ asm_operand_ok (op, constraint)
proper matching constraint, but we can't actually fail
the check if they didn't. Indicate that results are
inconclusive. */
while (*constraint >= '0' && *constraint <= '9')
constraint++;
result = -1;
break;
......@@ -2211,8 +2213,12 @@ preprocess_constraints ()
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
op_alt[j].matches = c - '0';
recog_op_alt[op_alt[j].matches][j].matched = i;
{
char *end;
op_alt[j].matches = strtoul (p - 1, &end, 10);
recog_op_alt[op_alt[j].matches][j].matched = i;
p = end;
}
break;
case 'm':
......@@ -2364,45 +2370,54 @@ constrain_operands (strict)
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
/* This operand must be the same as a previous one.
This kind of constraint is used for instructions such
as add when they take only two operands.
/* This operand must be the same as a previous one.
This kind of constraint is used for instructions such
as add when they take only two operands.
Note that the lower-numbered operand is passed first.
Note that the lower-numbered operand is passed first.
If we are not testing strictly, assume that this
constraint will be satisfied. */
If we are not testing strictly, assume that this constraint
will be satisfied. */
if (strict < 0)
val = 1;
else
{
rtx op1 = recog_data.operand[c - '0'];
rtx op2 = recog_data.operand[opno];
char *end;
int match;
/* A unary operator may be accepted by the predicate,
but it is irrelevant for matching constraints. */
if (GET_RTX_CLASS (GET_CODE (op1)) == '1')
op1 = XEXP (op1, 0);
if (GET_RTX_CLASS (GET_CODE (op2)) == '1')
op2 = XEXP (op2, 0);
match = strtoul (p - 1, &end, 10);
p = end;
val = operands_match_p (op1, op2);
}
if (strict < 0)
val = 1;
else
{
rtx op1 = recog_data.operand[match];
rtx op2 = recog_data.operand[opno];
matching_operands[opno] = c - '0';
matching_operands[c - '0'] = opno;
/* A unary operator may be accepted by the predicate,
but it is irrelevant for matching constraints. */
if (GET_RTX_CLASS (GET_CODE (op1)) == '1')
op1 = XEXP (op1, 0);
if (GET_RTX_CLASS (GET_CODE (op2)) == '1')
op2 = XEXP (op2, 0);
if (val != 0)
win = 1;
/* If output is *x and input is *--x,
arrange later to change the output to *--x as well,
since the output op is the one that will be printed. */
if (val == 2 && strict > 0)
{
funny_match[funny_match_index].this = opno;
funny_match[funny_match_index++].other = c - '0';
}
val = operands_match_p (op1, op2);
}
matching_operands[opno] = match;
matching_operands[match] = opno;
if (val != 0)
win = 1;
/* If output is *x and input is *--x, arrange later
to change the output to *--x as well, since the
output op is the one that will be printed. */
if (val == 2 && strict > 0)
{
funny_match[funny_match_index].this = opno;
funny_match[funny_match_index++].other = match;
}
}
break;
case 'p':
......
......@@ -1576,16 +1576,23 @@ find_matches (insn, matchp)
matchp->commutative[op_no] = op_no + 1;
matchp->commutative[op_no + 1] = op_no;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
c -= '0';
if (c < op_no && likely_spilled[(unsigned char) c])
break;
matchp->with[op_no] = c;
any_matches = 1;
if (matchp->commutative[op_no] >= 0)
matchp->with[matchp->commutative[op_no]] = c;
{
char *end;
unsigned long match = strtoul (p - 1, &end, 10);
p = end;
if (match < op_no && likely_spilled[match])
break;
matchp->with[op_no] = match;
any_matches = 1;
if (matchp->commutative[op_no] >= 0)
matchp->with[matchp->commutative[op_no]] = match;
}
break;
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'h':
case 'j': case 'k': case 'l': case 'p': case 'q': case 't': case 'u':
case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B':
......
......@@ -2551,7 +2551,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
}
else if (c >= '0' && c <= '9')
{
c -= '0';
c = strtoul (p - 1, &p, 10);
operands_match[c][i]
= operands_match_p (recog_data.operand[c],
recog_data.operand[i]);
......@@ -2939,8 +2940,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
c = strtoul (p - 1, &p, 10);
c -= '0';
this_alternative_matches[i] = c;
/* We are supposed to match a previous operand.
If we do, we win if that one did.
......
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