Commit d09a75ae by Richard Kenner

(expand_asm_operands): See if output operand permits register.

(expand_asm_operands): See if output operand permits register.  If
not, mark output addressable, call expand_operand on it, and give
error if not MEM.

From-SVN: r9923
parent 621061f4
......@@ -1411,41 +1411,73 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
tree type = TREE_TYPE (val);
tree val1;
int j;
int found_equal;
int found_equal = 0;
int allows_reg = 0;
/* If there's an erroneous arg, emit no insn. */
if (TREE_TYPE (val) == error_mark_node)
return;
/* Make sure constraint has `=' and does not have `+'. */
/* Make sure constraint has `=' and does not have `+'. Also, see
if it allows any register. Be liberal on the latter test, since
the worst that happens if we get it wrong is we issue an error
message. */
found_equal = 0;
for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)); j++)
{
if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] == '+')
{
error ("output operand constraint contains `+'");
return;
}
if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] == '=')
for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; j++)
switch (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j])
{
case '+':
error ("output operand constraint contains `+'");
return;
case '=':
found_equal = 1;
}
break;
case '?': case '!': case '*': case '%': case '&':
case '0': case '1': case '2': case '3': case '4':
case 'V': case 'm': case 'o': case '<': case '>':
case 'E': case 'F': case 'G': case 'H': case 'X':
case 's': case 'i': case 'n':
case 'I': case 'J': case 'K': case 'L': case 'M':
case 'N': case 'O': case 'P': case ',':
#ifdef EXTRA_CONSTRAINT
case 'Q': case 'R': case 'S': case 'T': case 'U':
#endif
break;
case 'p': case 'g': case 'r':
default:
allows_reg = 1;
break;
}
if (! found_equal)
{
error ("output operand constraint lacks `='");
return;
}
/* If an output operand is not a decl or indirect ref,
make a temporary to act as an intermediate. Make the asm insn
write into that, then our caller will copy it to the real output
operand. Likewise for promoted variables. */
/* 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
the real output operand. Likewise for promoted variables. */
if (TREE_CODE (val) == INDIRECT_REF
|| (TREE_CODE_CLASS (TREE_CODE (val)) == 'd'
&& ! (GET_CODE (DECL_RTL (val)) == REG
&& GET_MODE (DECL_RTL (val)) != TYPE_MODE (type))))
output_rtx[i] = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
&& GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
|| ! allows_reg)
{
if (! allows_reg)
mark_addressable (TREE_VALUE (tail));
output_rtx[i]
= expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
if (! allows_reg && GET_CODE (output_rtx[i]) != MEM)
error ("output number %d not directly addressable", i);
}
else
{
if (TYPE_MODE (type) == BLKmode)
......
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