expr.c (expand_expr, [...]): Move from the C++ frontend to the backend where it belongs.
authorMike Stump <mrs@gcc.gnu.org>
Fri, 17 May 1996 20:13:01 +0000 (20:13 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Fri, 17 May 1996 20:13:01 +0000 (20:13 +0000)
* 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

gcc/expr.c
gcc/tree.c
gcc/tree.def
gcc/tree.h

index 87305aa5dc93b71bb0ab0bad9f807f0af9ccb962..c10ff7b90e939ef6a5359abf57af04ba3954f5fd 100644 (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
index 7aa6c7736b1eded4e6dcb8f901f6ade862f8e993..fc4c983568a147f2968b2e959a663866ca3a04d6 100644 (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 ();
+    }
+}
 \f
 /* 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.
index 9de2ca01d99c493f9e3a84bbadfb0b1431bfbd1d..61f06a94a68f69e963a67b9d0c286f14f9186221 100644 (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.
index dea5d77e1236fbde600b77163de9f3335307aa05..ab2df453a5d4c3e897846f4321c79419acd75625 100644 (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.