+Mon Feb 1 20:00:40 1999 Richard Henderson <rth@cygnus.com>
+
+ * recog.c (check_asm_operands): Treat indeterminate operand ok
+ results as success. Try harder to resolve a matching constraint.
+ * stmt.c (expand_asm_operands): Recognize when an output operand's
+ constraint does not allow memory. Treat indeterminate operand ok
+ results as failure. Try harder to resolve a matching constraint.
+
Mon Feb 1 15:00:02 1999 Ken Raeburn <raeburn@cygnus.com>
Use varrays for constant-equivalence data:
for (i = 0; i < noperands; i++)
{
const char *c = constraints[i];
- if (ISDIGIT ((unsigned char)c[0]))
+ if (c[0] == '%')
+ c++;
+ if (ISDIGIT ((unsigned char)c[0]) && c[1] == '\0')
c = constraints[c[0] - '0'];
if (! asm_operand_ok (operands[i], c))
return template;
}
-/* Check if an asm_operand matches it's constraints. */
+/* Check if an asm_operand matches it's constraints.
+ Return > 0 if ok, = 0 if bad, < 0 if inconclusive. */
int
asm_operand_ok (op, constraint)
rtx op;
const char *constraint;
{
+ int result = 0;
+
/* Use constrain_operands after reload. */
if (reload_completed)
abort ();
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- /* Our caller is supposed to have given us the proper
- matching constraint. */
- /* abort (); */
+ /* For best results, our caller should have given us the
+ proper matching constraint, but we can't actually fail
+ the check if they didn't. Indicate that results are
+ inconclusive. */
+ result = -1;
break;
case 'p':
break;
case '<':
+ /* ??? Before flow, auto inc/dec insns are not supposed to exist,
+ excepting those that expand_call created. Further, on some
+ machines which do not have generalized auto inc/dec, an inc/dec
+ is not a memory_operand.
+
+ Match any memory and hope things are resolved after reload. */
+
if (GET_CODE (op) == MEM
- && (GET_CODE (XEXP (op, 0)) == PRE_DEC
+ && (1
+ || GET_CODE (XEXP (op, 0)) == PRE_DEC
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
return 1;
break;
case '>':
if (GET_CODE (op) == MEM
- && (GET_CODE (XEXP (op, 0)) == PRE_INC
+ && (1
+ || GET_CODE (XEXP (op, 0)) == PRE_INC
|| GET_CODE (XEXP (op, 0)) == POST_INC))
return 1;
break;
}
}
- return 0;
+ return result;
}
\f
/* Given an rtx *P, if it is a sum containing an integer constant term,
int j;
int is_inout = 0;
int allows_reg = 0;
+ int allows_mem = 0;
/* If there's an erroneous arg, emit no insn. */
if (TREE_TYPE (val) == error_mark_node)
break;
case '?': case '!': case '*': case '&':
- case 'V': case 'm': case 'o': case '<': case '>':
- case 'E': case 'F': case 'G': case 'H': case 'X':
+ case 'E': case 'F': case 'G': case 'H':
case 's': case 'i': case 'n':
case 'I': case 'J': case 'K': case 'L': case 'M':
case 'N': case 'O': case 'P': case ',':
error ("matching constraint not valid in output operand");
break;
- case 'p': case 'g': case 'r':
+ case 'V': case 'm': case 'o':
+ allows_mem = 1;
+ break;
+
+ case '<': case '>':
+ /* ??? Before flow, auto inc/dec insns are not supposed to exist,
+ excepting those that expand_call created. So match memory
+ and hope. */
+ allows_mem = 1;
+ break;
+
+ case 'g': case 'X':
+ allows_reg = 1;
+ allows_mem = 1;
+ break;
+
+ case 'p': case 'r':
default:
allows_reg = 1;
break;
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
+ if ((TREE_CODE (val) == INDIRECT_REF
+ && allows_mem)
|| (TREE_CODE_CLASS (TREE_CODE (val)) == 'd'
+ && (allows_mem || GET_CODE (DECL_RTL (val)) == REG)
&& ! (GET_CODE (DECL_RTL (val)) == REG
&& GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
|| ! allows_reg
if (! allows_reg && GET_CODE (output_rtx[i]) != MEM)
error ("output number %d not directly addressable", i);
+ if (! allows_mem && GET_CODE (output_rtx[i]) == MEM)
+ error ("output number %d not restored to memory", i);
}
else
{
}
/* Try and find the real constraint for this dup. */
- if (j == 0 && c_len == 1)
+ if ((j == 0 && c_len == 1)
+ || (j == 1 && c_len == 2 && constraint[0] == '%'))
{
tree o = outputs;
for (j = constraint[j] - '0'; j > 0; --j)
op = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
- if (! asm_operand_ok (op, constraint))
+ if (asm_operand_ok (op, constraint) <= 0)
{
if (allows_reg)
op = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))), op);