aboutsummaryrefslogtreecommitdiff
path: root/gcc/stmt.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>1999-01-15 10:43:47 -0800
committerRichard Henderson <rth@gcc.gnu.org>1999-01-15 10:43:47 -0800
commit1f06ee8d0db9c7444e2ff2210a21cca6c9602517 (patch)
tree76723342d0b784ed2b82cb4bb0bd1558554ff0a1 /gcc/stmt.c
parentd3694e346d97482464bc724ebecab03f20bf602b (diff)
downloadgcc-1f06ee8d0db9c7444e2ff2210a21cca6c9602517.zip
gcc-1f06ee8d0db9c7444e2ff2210a21cca6c9602517.tar.gz
gcc-1f06ee8d0db9c7444e2ff2210a21cca6c9602517.tar.bz2
expr.c (queued_subexp_p): Make public.
* expr.c (queued_subexp_p): Make public. * expr.h (queued_subexp_p): Declare it. * recog.c (asm_operand_ok): New function. (check_asm_operands): Use it. After reload, use constrain_operands instead. * recog.h (asm_operand_ok): Declare it. * stmt.c (expand_asm_operands): Use it to try harder to make asms initially satisfy their constraints. From-SVN: r24686
Diffstat (limited to 'gcc/stmt.c')
-rw-r--r--gcc/stmt.c100
1 files changed, 68 insertions, 32 deletions
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 4f2e911..4e972e9 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -1397,9 +1397,10 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
for (tail = inputs; tail; tail = TREE_CHAIN (tail))
{
int j;
- int allows_reg = 0;
- char *constraint;
+ int allows_reg = 0, allows_mem = 0;
+ char *constraint, *orig_constraint;
int c_len;
+ rtx op;
/* If there's an erroneous arg, emit no insn,
because the ASM_INPUT would get VOIDmode
@@ -1417,6 +1418,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
c_len = TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1;
constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail));
+ orig_constraint = constraint;
/* Make sure constraint has neither `=', `+', nor '&'. */
@@ -1424,19 +1426,28 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
switch (constraint[j])
{
case '+': case '=': case '&':
- error ("input operand constraint contains `%c'", constraint[j]);
- return;
+ if (constraint == orig_constraint)
+ {
+ error ("input operand constraint contains `%c'", constraint[j]);
+ return;
+ }
+ break;
case '%':
- if (i + 1 == ninputs - ninout)
+ if (constraint == orig_constraint
+ && i + 1 == ninputs - ninout)
{
error ("`%%' constraint used with last operand");
return;
}
break;
+ case 'V': case 'm': case 'o':
+ allows_mem = 1;
+ break;
+
+ 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':
case 'I': case 'J': case 'K': case 'L': case 'M':
@@ -1460,48 +1471,73 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
return;
}
+ /* Try and find the real constraint for this dup. */
+ if (j == 0 && c_len == 1)
+ {
+ tree o = outputs;
+ for (j = constraint[j] - '0'; j > 0; --j)
+ o = TREE_CHAIN (o);
+
+ c_len = TREE_STRING_LENGTH (TREE_PURPOSE (o)) - 1;
+ constraint = TREE_STRING_POINTER (TREE_PURPOSE (o));
+ j = 0;
+ break;
+ }
+
/* ... fall through ... */
- case 'p': case 'g': case 'r':
+ case 'p': case 'r':
default:
allows_reg = 1;
break;
+
+ case 'g':
+ allows_reg = 1;
+ allows_mem = 1;
+ break;
}
- if (! allows_reg)
+ if (! allows_reg && allows_mem)
mark_addressable (TREE_VALUE (tail));
- XVECEXP (body, 3, i) /* argvec */
- = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
- if (CONSTANT_P (XVECEXP (body, 3, i))
- && ! general_operand (XVECEXP (body, 3, i),
- TYPE_MODE (TREE_TYPE (TREE_VALUE (tail)))))
- {
- if (allows_reg)
- XVECEXP (body, 3, i)
- = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
- XVECEXP (body, 3, i));
- else
- XVECEXP (body, 3, i)
- = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
- XVECEXP (body, 3, i));
- }
+ op = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
- if (! allows_reg
- && (GET_CODE (XVECEXP (body, 3, i)) == REG
- || GET_CODE (XVECEXP (body, 3, i)) == SUBREG
- || GET_CODE (XVECEXP (body, 3, i)) == CONCAT))
+ if (! asm_operand_ok (op, constraint))
{
- tree type = TREE_TYPE (TREE_VALUE (tail));
- rtx memloc = assign_temp (type, 1, 1, 1);
+ if (allows_reg)
+ op = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))), op);
+ else if (!allows_mem)
+ warning ("asm operand %d probably doesn't match constraints", i);
+ else if (CONSTANT_P (op))
+ op = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
+ op);
+ else if (GET_CODE (op) == REG
+ || GET_CODE (op) == SUBREG
+ || GET_CODE (op) == CONCAT)
+ {
+ tree type = TREE_TYPE (TREE_VALUE (tail));
+ rtx memloc = assign_temp (type, 1, 1, 1);
- emit_move_insn (memloc, XVECEXP (body, 3, i));
- XVECEXP (body, 3, i) = memloc;
+ emit_move_insn (memloc, op);
+ op = memloc;
+ }
+ else if (GET_CODE (op) == MEM && MEM_VOLATILE_P (op))
+ /* We won't recognize volatile memory as available a
+ memory_operand at this point. Ignore it. */
+ ;
+ else if (queued_subexp_p (op))
+ ;
+ else
+ /* ??? Leave this only until we have experience with what
+ happens in combine and elsewhere when constraints are
+ not satisfied. */
+ warning ("asm operand %d probably doesn't match constraints", i);
}
+ XVECEXP (body, 3, i) = op;
XVECEXP (body, 4, i) /* constraints */
= gen_rtx_ASM_INPUT (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
- constraint);
+ orig_constraint);
i++;
}