stmt.c (n_occurrences): New static function.

* stmt.c (n_occurrences): New static function.
        (expand_asm_operands): Verify that all constrains match in the
        number of alternatives.
        Verify that '+' or '=' are at the beginning of an output constraint.
        Don't allow '&' for input operands.
        Verify that '%' isn't written for the last operand.
        * reload.c (find_reloads): Abort if an asm is found with invalid
        constraints; all possible problems ought to be checked for earlier.

From-SVN: r22911
This commit is contained in:
Bernd Schmidt 1998-10-07 22:07:40 -06:00 committed by Jeff Law
parent f1da172943
commit 2a230e9dc4
3 changed files with 112 additions and 70 deletions

View File

@ -1,3 +1,14 @@
Thu Oct 8 05:05:34 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
* stmt.c (n_occurrences): New static function.
(expand_asm_operands): Verify that all constrains match in the
number of alternatives.
Verify that '+' or '=' are at the beginning of an output constraint.
Don't allow '&' for input operands.
Verify that '%' isn't written for the last operand.
* reload.c (find_reloads): Abort if an asm is found with invalid
constraints; all possible problems ought to be checked for earlier.
Thu Oct 8 04:26:20 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
* flags.h (flag_branch_on_count_reg): Always declare

View File

@ -2442,15 +2442,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
bcopy ((char *) constraints, (char *) constraints1,
noperands * sizeof (char *));
n_alternatives = n_occurrences (',', constraints[0]) + 1;
for (i = 1; i < noperands; i++)
if (n_alternatives != n_occurrences (',', constraints[i]) + 1)
{
error_for_asm (insn, "operand constraints differ in number of alternatives");
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
n_reloads = 0;
return;
}
}
break;
}
@ -2510,15 +2501,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
{
/* The last operand should not be marked commutative. */
if (i == noperands - 1)
{
if (this_insn_is_asm)
warning_for_asm (this_insn,
"`%%' constraint used with last operand");
else
abort ();
}
else
commutative = i;
abort ();
commutative = i;
}
else if (c >= '0' && c <= '9')
{
@ -2528,13 +2513,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
/* An operand may not match itself. */
if (c == i)
{
if (this_insn_is_asm)
warning_for_asm (this_insn,
"operand %d has constraint %d", i, c);
else
abort ();
}
abort ();
/* If C can be commuted with C+1, and C might need to match I,
then C+1 might also need to match I. */
@ -3372,14 +3351,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
early_data = decompose (recog_operand[i]);
if (modified[i] == RELOAD_READ)
{
if (this_insn_is_asm)
warning_for_asm (this_insn,
"`&' constraint used with input operand");
else
abort ();
continue;
}
abort ();
if (this_alternative[i] == NO_REGS)
{

View File

@ -425,6 +425,7 @@ struct label_chain
static int using_eh_for_cleanups_p = 0;
static int n_occurrences PROTO((int, char *));
static void expand_goto_internal PROTO((tree, rtx, rtx));
static int expand_fixup PROTO((tree, rtx, rtx));
static void fixup_gotos PROTO((struct nesting *, rtx, tree,
@ -1096,8 +1097,18 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
f->stack_level = stack_level;
}
}
/* Return the number of times character C occurs in string S. */
static int
n_occurrences (c, s)
int c;
char *s;
{
int n = 0;
while (*s)
n += (*s++ == c);
return n;
}
/* Generate RTL for an asm statement (explicit assembler code).
BODY is a STRING_CST node containing the assembler code text,
@ -1184,13 +1195,38 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
last_expr_type = 0;
/* Check that the number of alternatives is constant across all
operands. */
if (outputs || inputs)
{
tree tmp = TREE_PURPOSE (outputs ? outputs : inputs);
int nalternatives = n_occurrences (',', TREE_STRING_POINTER (tmp));
tree next = inputs;
tmp = outputs;
while (tmp)
{
char *constraint = TREE_STRING_POINTER (TREE_PURPOSE (tmp));
if (n_occurrences (',', constraint) != nalternatives)
{
error ("operand constraints for `asm' differ in number of alternatives");
return;
}
if (TREE_CHAIN (tmp))
tmp = TREE_CHAIN (tmp);
else
tmp = next, next = 0;
}
}
for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
{
tree val = TREE_VALUE (tail);
tree type = TREE_TYPE (val);
char *constraint;
int c_len;
int j;
int found_equal = 0;
int found_plus = 0;
int is_inout = 0;
int allows_reg = 0;
/* If there's an erroneous arg, emit no insn. */
@ -1202,27 +1238,43 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
the worst that happens if we get it wrong is we issue an error
message. */
for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; j++)
switch (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j])
c_len = TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1;
constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail));
if (c_len == 0
|| (constraint[0] != '=' && constraint[0] != '+'))
{
error ("output operand constraint lacks `='");
return;
}
is_inout = constraint[0] == '+';
/* Replace '+' with '='. */
constraint[0] = '=';
/* Make sure we can specify the matching operand. */
if (is_inout && i > 9)
{
error ("output operand constraint %d contains `+'", i);
return;
}
for (j = 1; j < c_len; j++)
switch (constraint[j])
{
case '+':
/* Make sure we can specify the matching operand. */
if (i > 9)
case '=':
error ("operand constraint contains '+' or '=' at illegal position.");
return;
case '%':
if (i + 1 == ninputs + noutputs)
{
error ("output operand constraint %d contains `+'", i);
error ("`%%' constraint used with last operand");
return;
}
/* Replace '+' with '='. */
TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] = '=';
found_plus = 1;
break;
case '=':
found_equal = 1;
break;
case '?': case '!': case '*': case '%': case '&':
case '?': case '!': case '*': case '&':
case 'V': case 'm': case 'o': case '<': case '>':
case 'E': case 'F': case 'G': case 'H': case 'X':
case 's': case 'i': case 'n':
@ -1244,12 +1296,6 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
break;
}
if (! found_equal && ! found_plus)
{
error ("output operand constraint lacks `='");
return;
}
/* If an output operand is not a decl or indirect ref and our constraint
allows a register, make a temporary to act as an intermediate.
Make the asm insn write into that, then our caller will copy it to
@ -1260,7 +1306,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
&& ! (GET_CODE (DECL_RTL (val)) == REG
&& GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
|| ! allows_reg
|| found_plus)
|| is_inout)
{
if (! allows_reg)
mark_addressable (TREE_VALUE (tail));
@ -1278,7 +1324,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
TREE_VALUE (tail) = make_tree (type, output_rtx[i]);
}
if (found_plus)
if (is_inout)
{
inout_mode[ninout] = TYPE_MODE (TREE_TYPE (TREE_VALUE (tail)));
inout_opnum[ninout++] = i;
@ -1311,12 +1357,16 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
{
int j;
int allows_reg = 0;
char *constraint;
int c_len;
/* If there's an erroneous arg, emit no insn,
because the ASM_INPUT would get VOIDmode
and that could cause a crash in reload. */
if (TREE_TYPE (TREE_VALUE (tail)) == error_mark_node)
return;
/* ??? Can this happen, and does the error message make any sense? */
if (TREE_PURPOSE (tail) == NULL_TREE)
{
error ("hard register `%s' listed as input operand to `asm'",
@ -1324,17 +1374,27 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
return;
}
/* Make sure constraint has neither `=' nor `+'. */
c_len = TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1;
constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail));
for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; j++)
switch (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j])
/* Make sure constraint has neither `=', `+', nor '&'. */
for (j = 0; j < c_len; j++)
switch (constraint[j])
{
case '+': case '=':
error ("input operand constraint contains `%c'",
TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]);
case '+': case '=': case '&':
error ("input operand constraint contains `%c'", constraint[j]);
return;
case '?': case '!': case '*': case '%': case '&':
case '%':
if (i + 1 == ninputs - ninout)
{
error ("`%%' constraint used with last operand");
return;
}
break;
case '?': case '!': case '*':
case 'V': case 'm': case 'o': case '<': case '>':
case 'E': case 'F': case 'G': case 'H': case 'X':
case 's': case 'i': case 'n':
@ -1352,8 +1412,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
operands to memory. */
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]
>= '0' + noutputs)
if (constraint[j] >= '0' + noutputs)
{
error
("matching constraint references invalid operand number");
@ -1398,10 +1457,10 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
emit_move_insn (memloc, XVECEXP (body, 3, i));
XVECEXP (body, 3, i) = memloc;
}
XVECEXP (body, 4, i) /* constraints */
= gen_rtx_ASM_INPUT (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
TREE_STRING_POINTER (TREE_PURPOSE (tail)));
constraint);
i++;
}