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:
Mike Stump 1996-05-17 20:13:01 +00:00
parent 520e7ff5c7
commit 679163cf4d
4 changed files with 113 additions and 0 deletions

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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.