mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-21 12:41:19 +08:00
stmt.c (parse_input_constraint): Break out from ...
* stmt.c (parse_input_constraint): Break out from ... (expand_asm_operands): ... here. Loop over the operands twice, the first time only calling mark_addressable. Correct and simplify the conditions for spilling an output operand to memory. From-SVN: r48298
This commit is contained in:
parent
99407cf2f1
commit
6be2e1f88c
@ -1,3 +1,10 @@
|
||||
2001-12-23 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* stmt.c (parse_input_constraint): Break out from ...
|
||||
(expand_asm_operands): ... here. Loop over the operands twice,
|
||||
the first time only calling mark_addressable. Correct and simplify
|
||||
the conditions for spilling an output operand to memory.
|
||||
|
||||
2001-12-23 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* config/alpha/alpha.c (call_operand) [OSF]: Disallow virtual regs.
|
||||
@ -46,13 +53,13 @@
|
||||
|
||||
2001-12-22 Aldy Hernandez <aldyh@redhat.com>
|
||||
|
||||
* config/rs6000/rs6000.h (rs6000_builtins): Add vsldoi variants.
|
||||
* config/rs6000/rs6000.h (rs6000_builtins): Add vsldoi variants.
|
||||
|
||||
* config/rs6000/rs6000.md ("altivec_vsldoi_*"): Same.
|
||||
* config/rs6000/rs6000.md ("altivec_vsldoi_*"): Same.
|
||||
|
||||
* config/rs6000/rs6000.c: Clean up some spacing and indentation.
|
||||
(altivec_init_builtins): Add tree types for builtins with 4 bit
|
||||
literals.
|
||||
* config/rs6000/rs6000.c: Clean up some spacing and indentation.
|
||||
(altivec_init_builtins): Add tree types for builtins with 4 bit
|
||||
literals.
|
||||
(bdesc_3arg): Add vsldoi variants.
|
||||
|
||||
2001-12-22 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
||||
@ -248,16 +255,16 @@ Fri Dec 21 17:30:15 2001 Jeffrey A Law (law@redhat.com)
|
||||
2001-12-20 Nick Clifton <nickc@cambridge.redhat.com>
|
||||
|
||||
* config/arm/arm.c (arm_compute_save_reg0_reg12_mask): New
|
||||
function. Compute which of registers r0 through r12 should be
|
||||
function. Compute which of registers r0 through r12 should be
|
||||
saved onto the stack during a function's prologue.
|
||||
(arm_compute_save_reg_mask): Use
|
||||
arm_compute_save_reg0_reg12_mask.
|
||||
(arm_compute_initial_elimination_offset): Use
|
||||
arm_compute_save_reg0_reg12_mask.
|
||||
(arm_compute_save_reg_mask): Use
|
||||
arm_compute_save_reg0_reg12_mask.
|
||||
(arm_compute_initial_elimination_offset): Use
|
||||
arm_compute_save_reg0_reg12_mask.
|
||||
|
||||
(arm_expand_prologue): Do not mark as save of the IP register
|
||||
for an interrupt handler as being part of the frame creation
|
||||
code.
|
||||
(arm_expand_prologue): Do not mark as save of the IP register
|
||||
for an interrupt handler as being part of the frame creation
|
||||
code.
|
||||
|
||||
2001-12-20 Richard Henderson <rth@redhat.com>
|
||||
|
||||
@ -320,30 +327,30 @@ Thu Dec 20 16:58:46 CET 2001 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
2001-12-19 Aldy Hernandez <aldyh@redhat.com>
|
||||
|
||||
* doc/install.texi: Add documentation for --enable-altivec.
|
||||
* doc/install.texi: Add documentation for --enable-altivec.
|
||||
|
||||
* config.gcc: Add support for --enable-altivec.
|
||||
* config.gcc: Add support for --enable-altivec.
|
||||
|
||||
* config/rs6000/altivec.h: New.
|
||||
* config/rs6000/altivec.h: New.
|
||||
|
||||
* config/rs6000/linuxaltivec.h (SUBSUBTARGET_OVERRIDE_OPTIONS):
|
||||
Define. Fix typo.
|
||||
* config/rs6000/linuxaltivec.h (SUBSUBTARGET_OVERRIDE_OPTIONS):
|
||||
Define. Fix typo.
|
||||
|
||||
* config/rs6000/rs6000.c (vrsave_operation): Change unspec to
|
||||
* config/rs6000/rs6000.c (vrsave_operation): Change unspec to
|
||||
unspec_volatile.
|
||||
(generate_set_vrsave): Generate the unspec here instead of calling
|
||||
an .md pattern.
|
||||
(generate_set_vrsave): Use gen_rtvec.
|
||||
(rs6000_emit_prologue): Replace call to gen_get_vrsave with
|
||||
gen_rtx_SET.
|
||||
(generate_set_vrsave): Generate the unspec here instead of calling
|
||||
an .md pattern.
|
||||
(generate_set_vrsave): Use gen_rtvec.
|
||||
(rs6000_emit_prologue): Replace call to gen_get_vrsave with
|
||||
gen_rtx_SET.
|
||||
|
||||
* config/rs6000/rs6000.md ("*movsi_internal1"): Add constraints
|
||||
* config/rs6000/rs6000.md ("*movsi_internal1"): Add constraints
|
||||
for setting special registers.
|
||||
("*set_vrsave_internal"): Use unspec_volatile.
|
||||
("set_vrsave"): Remove.
|
||||
("get_vrsave"): Remove.
|
||||
("*set_vrsave_internal"): Use unspec_volatile.
|
||||
("set_vrsave"): Remove.
|
||||
("get_vrsave"): Remove.
|
||||
|
||||
* config/rs6000/rs6000.h (REG_CLASS_CONTENTS): Add vrsave to
|
||||
* config/rs6000/rs6000.h (REG_CLASS_CONTENTS): Add vrsave to
|
||||
SPECIAL_REGS.
|
||||
|
||||
2001-12-19 Bruce Korb <bkorb@gnu.org>
|
||||
|
380
gcc/stmt.c
380
gcc/stmt.c
@ -397,6 +397,9 @@ struct stmt_status
|
||||
static int using_eh_for_cleanups_p = 0;
|
||||
|
||||
static int n_occurrences PARAMS ((int, const char *));
|
||||
static bool parse_input_constraint PARAMS ((const char **, int, int, int,
|
||||
int, const char * const *,
|
||||
bool *, bool *));
|
||||
static void expand_goto_internal PARAMS ((tree, rtx, rtx));
|
||||
static int expand_fixup PARAMS ((tree, rtx, rtx));
|
||||
static rtx expand_nl_handler_label PARAMS ((rtx, rtx));
|
||||
@ -1307,13 +1310,8 @@ expand_asm (body)
|
||||
Returns TRUE if all went well; FALSE if an error occurred. */
|
||||
|
||||
bool
|
||||
parse_output_constraint (constraint_p,
|
||||
operand_num,
|
||||
ninputs,
|
||||
noutputs,
|
||||
allows_mem,
|
||||
allows_reg,
|
||||
is_inout)
|
||||
parse_output_constraint (constraint_p, operand_num, ninputs, noutputs,
|
||||
allows_mem, allows_reg, is_inout)
|
||||
const char **constraint_p;
|
||||
int operand_num;
|
||||
int ninputs;
|
||||
@ -1444,6 +1442,131 @@ parse_output_constraint (constraint_p,
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Similar, but for input constraints. */
|
||||
|
||||
static bool
|
||||
parse_input_constraint (constraint_p, input_num, ninputs, noutputs, ninout,
|
||||
constraints, allows_mem, allows_reg)
|
||||
const char **constraint_p;
|
||||
int input_num;
|
||||
int ninputs;
|
||||
int noutputs;
|
||||
int ninout;
|
||||
const char * const * constraints;
|
||||
bool *allows_mem;
|
||||
bool *allows_reg;
|
||||
{
|
||||
const char *constraint = *constraint_p;
|
||||
const char *orig_constraint = constraint;
|
||||
size_t c_len = strlen (constraint);
|
||||
size_t j;
|
||||
|
||||
/* Assume the constraint doesn't allow the use of either
|
||||
a register or memory. */
|
||||
*allows_mem = false;
|
||||
*allows_reg = false;
|
||||
|
||||
/* Make sure constraint has neither `=', `+', nor '&'. */
|
||||
|
||||
for (j = 0; j < c_len; j++)
|
||||
switch (constraint[j])
|
||||
{
|
||||
case '+': case '=': case '&':
|
||||
if (constraint == orig_constraint)
|
||||
{
|
||||
error ("input operand constraint contains `%c'", constraint[j]);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
if (constraint == orig_constraint
|
||||
&& input_num + 1 == ninputs - ninout)
|
||||
{
|
||||
error ("`%%' constraint used with last operand");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'V': case 'm': case 'o':
|
||||
*allows_mem = true;
|
||||
break;
|
||||
|
||||
case '<': case '>':
|
||||
case '?': case '!': case '*': case '#':
|
||||
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 ',':
|
||||
break;
|
||||
|
||||
/* Whether or not a numeric constraint allows a register is
|
||||
decided by the matching constraint, and so there is no need
|
||||
to do anything special with them. We must handle them in
|
||||
the default case, so that we don't unnecessarily force
|
||||
operands to memory. */
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
{
|
||||
char *end;
|
||||
unsigned long match;
|
||||
|
||||
match = strtoul (constraint + j, &end, 10);
|
||||
if (match >= (unsigned long) noutputs)
|
||||
{
|
||||
error ("matching constraint references invalid operand number");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Try and find the real constraint for this dup. Only do this
|
||||
if the matching constraint is the only alternative. */
|
||||
if (*end == '\0'
|
||||
&& (j == 0 || (j == 1 && constraint[0] == '%')))
|
||||
{
|
||||
constraint = constraints[match];
|
||||
*constraint_p = constraint;
|
||||
c_len = strlen (constraint);
|
||||
j = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
j = end - constraint;
|
||||
}
|
||||
/* Fall through. */
|
||||
|
||||
case 'p': case 'r':
|
||||
*allows_reg = true;
|
||||
break;
|
||||
|
||||
case 'g': case 'X':
|
||||
*allows_reg = true;
|
||||
*allows_mem = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (! ISALPHA (constraint[j]))
|
||||
{
|
||||
error ("invalid punctuation `%c' in constraint", constraint[j]);
|
||||
return false;
|
||||
}
|
||||
if (REG_CLASS_FROM_LETTER (constraint[j]) != NO_REGS)
|
||||
*allows_reg = true;
|
||||
#ifdef EXTRA_CONSTRAINT
|
||||
else
|
||||
{
|
||||
/* Otherwise we can't assume anything about the nature of
|
||||
the constraint except that it isn't purely registers.
|
||||
Treat it like "g" and hope for the best. */
|
||||
*allows_reg = true;
|
||||
*allows_mem = true;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Generate RTL for an asm statement with arguments.
|
||||
STRING is the instruction template.
|
||||
OUTPUTS is a list of output arguments (lvalues); INPUTS a list of inputs.
|
||||
@ -1472,7 +1595,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|
||||
rtx body;
|
||||
int ninputs = list_length (inputs);
|
||||
int noutputs = list_length (outputs);
|
||||
int ninout = 0;
|
||||
int ninout;
|
||||
int nclobbers;
|
||||
tree tail;
|
||||
int i;
|
||||
@ -1524,10 +1647,15 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|
||||
|
||||
last_expr_type = 0;
|
||||
|
||||
/* First pass over inputs and outputs checks validity and sets
|
||||
mark_addressable if needed. */
|
||||
|
||||
ninout = 0;
|
||||
for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
|
||||
{
|
||||
tree val = TREE_VALUE (tail);
|
||||
tree type = TREE_TYPE (val);
|
||||
const char *constraint;
|
||||
bool is_inout;
|
||||
bool allows_reg;
|
||||
bool allows_mem;
|
||||
@ -1536,22 +1664,67 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|
||||
if (type == error_mark_node)
|
||||
return;
|
||||
|
||||
/* 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. */
|
||||
|
||||
/* Try to parse the output constraint. If that fails, there's
|
||||
no point in going further. */
|
||||
if (!parse_output_constraint (&constraints[i],
|
||||
i,
|
||||
ninputs,
|
||||
noutputs,
|
||||
&allows_mem,
|
||||
&allows_reg,
|
||||
&is_inout))
|
||||
constraint = constraints[i];
|
||||
if (!parse_output_constraint (&constraint, i, ninputs, noutputs,
|
||||
&allows_mem, &allows_reg, &is_inout))
|
||||
return;
|
||||
|
||||
if (! allows_reg
|
||||
&& (allows_mem
|
||||
|| is_inout
|
||||
|| (DECL_P (val)
|
||||
&& GET_CODE (DECL_RTL (val)) == REG
|
||||
&& GET_MODE (DECL_RTL (val)) != TYPE_MODE (type))))
|
||||
mark_addressable (val);
|
||||
|
||||
if (is_inout)
|
||||
ninout++;
|
||||
}
|
||||
|
||||
ninputs += ninout;
|
||||
if (ninputs + noutputs > MAX_RECOG_OPERANDS)
|
||||
{
|
||||
error ("more than %d operands in `asm'", MAX_RECOG_OPERANDS);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0, tail = inputs; tail; i++, tail = TREE_CHAIN (tail))
|
||||
{
|
||||
bool allows_reg, allows_mem;
|
||||
const char *constraint;
|
||||
|
||||
/* 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;
|
||||
|
||||
constraint = constraints[i + noutputs];
|
||||
if (! parse_input_constraint (&constraint, i, ninputs, noutputs, ninout,
|
||||
constraints, &allows_mem, &allows_reg))
|
||||
return;
|
||||
|
||||
if (! allows_reg && allows_mem)
|
||||
mark_addressable (TREE_VALUE (tail));
|
||||
}
|
||||
|
||||
/* Second pass evaluates arguments. */
|
||||
|
||||
ninout = 0;
|
||||
for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
|
||||
{
|
||||
tree val = TREE_VALUE (tail);
|
||||
tree type = TREE_TYPE (val);
|
||||
bool is_inout;
|
||||
bool allows_reg;
|
||||
bool allows_mem;
|
||||
|
||||
if (!parse_output_constraint (&constraints[i], i, ninputs,
|
||||
noutputs, &allows_mem, &allows_reg,
|
||||
&is_inout))
|
||||
abort ();
|
||||
|
||||
/* 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
|
||||
@ -1569,12 +1742,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|
||||
|| ! allows_reg
|
||||
|| is_inout)
|
||||
{
|
||||
if (! allows_reg)
|
||||
mark_addressable (TREE_VALUE (tail));
|
||||
|
||||
output_rtx[i]
|
||||
= expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode,
|
||||
EXPAND_WRITE);
|
||||
output_rtx[i] = expand_expr (val, NULL_RTX, VOIDmode, EXPAND_WRITE);
|
||||
|
||||
if (! allows_reg && GET_CODE (output_rtx[i]) != MEM)
|
||||
error ("output number %d not directly addressable", i);
|
||||
@ -1597,18 +1765,11 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|
||||
|
||||
if (is_inout)
|
||||
{
|
||||
inout_mode[ninout] = TYPE_MODE (TREE_TYPE (TREE_VALUE (tail)));
|
||||
inout_mode[ninout] = TYPE_MODE (type);
|
||||
inout_opnum[ninout++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
ninputs += ninout;
|
||||
if (ninputs + noutputs > MAX_RECOG_OPERANDS)
|
||||
{
|
||||
error ("more than %d operands in `asm'", MAX_RECOG_OPERANDS);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make vectors for the expression-rtx, constraint strings,
|
||||
and named operands. */
|
||||
|
||||
@ -1628,154 +1789,40 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|
||||
|
||||
for (i = 0, tail = inputs; tail; tail = TREE_CHAIN (tail), ++i)
|
||||
{
|
||||
int j;
|
||||
int allows_reg = 0, allows_mem = 0;
|
||||
const char *constraint, *orig_constraint;
|
||||
int c_len;
|
||||
bool allows_reg, allows_mem;
|
||||
const char *constraint;
|
||||
tree val, type;
|
||||
rtx op;
|
||||
|
||||
/* 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;
|
||||
constraint = constraints[i + noutputs];
|
||||
if (! parse_input_constraint (&constraint, i, ninputs, noutputs, ninout,
|
||||
constraints, &allows_mem, &allows_reg))
|
||||
abort ();
|
||||
|
||||
/* ??? 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'",
|
||||
TREE_STRING_POINTER (TREE_VALUE (tail)) );
|
||||
return;
|
||||
}
|
||||
generating_concat_p = 0;
|
||||
|
||||
orig_constraint = constraint = constraints[i + noutputs];
|
||||
c_len = strlen (constraint);
|
||||
|
||||
/* Make sure constraint has neither `=', `+', nor '&'. */
|
||||
|
||||
for (j = 0; j < c_len; j++)
|
||||
switch (constraint[j])
|
||||
{
|
||||
case '+': case '=': case '&':
|
||||
if (constraint == orig_constraint)
|
||||
{
|
||||
error ("input operand constraint contains `%c'",
|
||||
constraint[j]);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
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 '#':
|
||||
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 ',':
|
||||
break;
|
||||
|
||||
/* Whether or not a numeric constraint allows a register is
|
||||
decided by the matching constraint, and so there is no need
|
||||
to do anything special with them. We must handle them in
|
||||
the default case, so that we don't unnecessarily force
|
||||
operands to memory. */
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
{
|
||||
char *end;
|
||||
unsigned long match;
|
||||
|
||||
match = strtoul (constraint + j, &end, 10);
|
||||
if (match >= (unsigned long) noutputs)
|
||||
{
|
||||
error ("matching constraint references invalid operand number");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try and find the real constraint for this dup. Only do
|
||||
this if the matching constraint is the only alternative. */
|
||||
if (*end == '\0'
|
||||
&& (j == 0 || (j == 1 && constraint[0] == '%')))
|
||||
{
|
||||
constraint = constraints[match];
|
||||
c_len = strlen (constraint);
|
||||
j = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
j = end - constraint;
|
||||
}
|
||||
/* Fall through. */
|
||||
|
||||
case 'p': case 'r':
|
||||
allows_reg = 1;
|
||||
break;
|
||||
|
||||
case 'g': case 'X':
|
||||
allows_reg = 1;
|
||||
allows_mem = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (! ISALPHA (constraint[j]))
|
||||
{
|
||||
error ("invalid punctuation `%c' in constraint",
|
||||
constraint[j]);
|
||||
return;
|
||||
}
|
||||
if (REG_CLASS_FROM_LETTER (constraint[j]) != NO_REGS)
|
||||
allows_reg = 1;
|
||||
#ifdef EXTRA_CONSTRAINT
|
||||
else
|
||||
{
|
||||
/* Otherwise we can't assume anything about the nature of
|
||||
the constraint except that it isn't purely registers.
|
||||
Treat it like "g" and hope for the best. */
|
||||
allows_reg = 1;
|
||||
allows_mem = 1;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
if (! allows_reg && allows_mem)
|
||||
mark_addressable (TREE_VALUE (tail));
|
||||
|
||||
op = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
|
||||
val = TREE_VALUE (tail);
|
||||
type = TREE_TYPE (val);
|
||||
op = expand_expr (val, NULL_RTX, VOIDmode, 0);
|
||||
|
||||
/* Never pass a CONCAT to an ASM. */
|
||||
generating_concat_p = 0;
|
||||
if (GET_CODE (op) == CONCAT)
|
||||
op = force_reg (GET_MODE (op), op);
|
||||
|
||||
if (asm_operand_ok (op, constraint) <= 0)
|
||||
{
|
||||
if (allows_reg)
|
||||
op = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))), op);
|
||||
op = force_reg (TYPE_MODE (type), op);
|
||||
else if (!allows_mem)
|
||||
warning ("asm operand %d probably doesn't match constraints",
|
||||
i + noutputs);
|
||||
else if (CONSTANT_P (op))
|
||||
op = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
|
||||
op);
|
||||
op = force_const_mem (TYPE_MODE (type), op);
|
||||
else if (GET_CODE (op) == REG
|
||||
|| GET_CODE (op) == SUBREG
|
||||
|| GET_CODE (op) == ADDRESSOF
|
||||
|| GET_CODE (op) == CONCAT)
|
||||
{
|
||||
tree type = TREE_TYPE (TREE_VALUE (tail));
|
||||
tree qual_type = build_qualified_type (type,
|
||||
(TYPE_QUALS (type)
|
||||
| TYPE_QUAL_CONST));
|
||||
@ -1786,9 +1833,10 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|
||||
}
|
||||
|
||||
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. */
|
||||
;
|
||||
{
|
||||
/* We won't recognize volatile memory as available a
|
||||
memory_operand at this point. Ignore it. */
|
||||
}
|
||||
else if (queued_subexp_p (op))
|
||||
;
|
||||
else
|
||||
@ -1798,12 +1846,12 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|
||||
warning ("asm operand %d probably doesn't match constraints",
|
||||
i + noutputs);
|
||||
}
|
||||
|
||||
generating_concat_p = old_generating_concat_p;
|
||||
ASM_OPERANDS_INPUT (body, i) = op;
|
||||
|
||||
ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, i)
|
||||
= gen_rtx_ASM_INPUT (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
|
||||
orig_constraint);
|
||||
= gen_rtx_ASM_INPUT (TYPE_MODE (type), constraints[i + noutputs]);
|
||||
}
|
||||
|
||||
/* Protect all the operands from the queue now that they have all been
|
||||
|
10
gcc/testsuite/gcc.c-torture/compile/20011205-1.c
Normal file
10
gcc/testsuite/gcc.c-torture/compile/20011205-1.c
Normal file
@ -0,0 +1,10 @@
|
||||
/* Failure to mark_addressable all operands before evaluation means we
|
||||
don't set up the proper temporaries, which leaves us with an asm that
|
||||
doesn't match its contraints. */
|
||||
|
||||
long foo()
|
||||
{
|
||||
long x;
|
||||
asm("" : "=r"(x) : "m"(x));
|
||||
return x;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user