expr.c (expand_expr, [...]): Move from the C++ frontend to the backend where it belongs.
* expr.c (expand_expr, cond UNSAVE_EXPR): Move from the C++ frontend to the backend where it belongs. * tree.c (unsave_expr): Ditto. (unsave_expr_now): Ditto. * tree.def (UNSAVE_EXPR): Ditto. * tree.h (unsave_expr): Ditto. (unsave_expr_now): Ditto. From-SVN: r12015
This commit is contained in:
parent
520e7ff5c7
commit
679163cf4d
|
@ -4905,6 +4905,14 @@ expand_expr (exp, target, tmode, modifier)
|
|||
|
||||
return SAVE_EXPR_RTL (exp);
|
||||
|
||||
case UNSAVE_EXPR:
|
||||
{
|
||||
rtx temp;
|
||||
temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
|
||||
TREE_OPERAND (exp, 0) = unsave_expr_now (TREE_OPERAND (exp, 0));
|
||||
return temp;
|
||||
}
|
||||
|
||||
case PLACEHOLDER_EXPR:
|
||||
/* If there is an object on the head of the placeholder list,
|
||||
see if some object in it's references is of type TYPE. For
|
||||
|
|
85
gcc/tree.c
85
gcc/tree.c
|
@ -2156,6 +2156,91 @@ save_expr (expr)
|
|||
TREE_SIDE_EFFECTS (t) = 1;
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Arrange for an expression to be expanded multiple independent
|
||||
times. This is useful for cleanup actions, as the backend can
|
||||
expand them multiple times in different places. */
|
||||
tree
|
||||
unsave_expr (expr)
|
||||
tree expr;
|
||||
{
|
||||
tree t;
|
||||
|
||||
/* If this is already protected, no sense in protecting it again. */
|
||||
if (TREE_CODE (expr) == UNSAVE_EXPR)
|
||||
return expr;
|
||||
|
||||
t = build1 (UNSAVE_EXPR, TREE_TYPE (expr), expr);
|
||||
TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr);
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Modify a tree in place so that all the evaluate only once things
|
||||
are cleared out. Return the EXPR given. */
|
||||
tree
|
||||
unsave_expr_now (expr)
|
||||
tree expr;
|
||||
{
|
||||
enum tree_code code;
|
||||
register int i;
|
||||
|
||||
if (expr == NULL_TREE)
|
||||
return expr;
|
||||
|
||||
code = TREE_CODE (expr);
|
||||
switch (code)
|
||||
{
|
||||
case SAVE_EXPR:
|
||||
SAVE_EXPR_RTL (expr) = NULL_RTX;
|
||||
break;
|
||||
|
||||
case TARGET_EXPR:
|
||||
sorry ("TARGET_EXPR reused inside UNSAVE_EXPR");
|
||||
break;
|
||||
|
||||
case RTL_EXPR:
|
||||
warning ("RTL_EXPR reused inside UNSAVE_EXPR");
|
||||
RTL_EXPR_SEQUENCE (expr) = NULL_RTX;
|
||||
break;
|
||||
|
||||
case CALL_EXPR:
|
||||
CALL_EXPR_RTL (expr) = NULL_RTX;
|
||||
if (TREE_OPERAND (expr, 1)
|
||||
&& TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST)
|
||||
{
|
||||
tree exp = TREE_OPERAND (expr, 1);
|
||||
while (exp)
|
||||
{
|
||||
unsave_expr_now (TREE_VALUE (exp));
|
||||
exp = TREE_CHAIN (exp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (TREE_CODE_CLASS (code))
|
||||
{
|
||||
case 'c': /* a constant */
|
||||
case 't': /* a type node */
|
||||
case 'x': /* something random, like an identifier or an ERROR_MARK. */
|
||||
case 'd': /* A decl node */
|
||||
case 'b': /* A block node */
|
||||
return expr;
|
||||
|
||||
case 'e': /* an expression */
|
||||
case 'r': /* a reference */
|
||||
case 's': /* an expression with side effects */
|
||||
case '<': /* a comparison expression */
|
||||
case '2': /* a binary arithmetic expression */
|
||||
case '1': /* a unary arithmetic expression */
|
||||
for (i = tree_code_length[(int) code] - 1; i >= 0; i--)
|
||||
unsave_expr_now (TREE_OPERAND (expr, i));
|
||||
return expr;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size
|
||||
or offset that depends on a field within a record.
|
||||
|
|
|
@ -646,6 +646,15 @@ DEFTREECODE (NON_LVALUE_EXPR, "non_lvalue_expr", "1", 1)
|
|||
nonzero only after the expression has been computed. */
|
||||
DEFTREECODE (SAVE_EXPR, "save_expr", "e", 3)
|
||||
|
||||
/* For a UNSAVE_EXPR, operand 0 is the value to unsave. By unsave, we
|
||||
mean that all _EXPRs such as TARGET_EXPRs, SAVE_EXPRs,
|
||||
CALL_EXPRs and RTL_EXPRs, that are protected
|
||||
from being evaluated more than once should be reset so that a new
|
||||
expand_expr call of this expr will cause those to be re-evaluated.
|
||||
This is useful when we want to reuse a tree in different places,
|
||||
but where we must re-expand. */
|
||||
DEFTREECODE (UNSAVE_EXPR, "unsave_expr", "e", 1)
|
||||
|
||||
/* Represents something whose RTL has already been expanded
|
||||
as a sequence which should be emitted when this expression is expanded.
|
||||
The first operand is the RTL to emit. It is the first of a chain of insns.
|
||||
|
|
11
gcc/tree.h
11
gcc/tree.h
|
@ -1436,6 +1436,17 @@ extern int lvalue_or_else PROTO((tree, char *));
|
|||
|
||||
extern tree save_expr PROTO((tree));
|
||||
|
||||
/* unsave_expr (EXP) returns an expression equivalent to EXP but it
|
||||
can be used multiple times and will evaluate EXP, in it's entirety
|
||||
each time. */
|
||||
|
||||
extern tree unsave_expr PROTO((tree));
|
||||
|
||||
/* unsave_expr_now (EXP) resets EXP in place, so that it can be
|
||||
expanded again. */
|
||||
|
||||
extern tree unsave_expr_now PROTO((tree));
|
||||
|
||||
/* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size
|
||||
or offset that depends on a field within a record.
|
||||
|
||||
|
|
Loading…
Reference in New Issue