]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
calls.c (expand_call): Only destroy temporaries at the end of function calls, if...
authorMike Stump <mrs@gcc.gnu.org>
Fri, 13 May 1994 00:19:57 +0000 (00:19 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Fri, 13 May 1994 00:19:57 +0000 (00:19 +0000)
        * calls.c (expand_call): Only destroy temporaries at the end
        of function calls, if flag_short_temps is set.
        * expr.c (safe_from_p, expand_expr): Handle CLEANUP_POINT_EXPRs.
        * expr.c (expand_expr): Improve handling of temporaries inside
        COND_EXPRs, cures call to sorry.
        * expr.c (defer_cleanups_to): New routine to handle the deferral
        of cleanups.
        * flags.h (flag_short_temps): New flag, to allow better control
        over the lifetime of temporaries.
        * toplev.c (flag_short_temps, lang_options): Ditto.
        * tree.def (CLEANUP_POINT_EXPR): Add, to allow better control over
        the lifetime of temporaries.

From-SVN: r7289

gcc/calls.c
gcc/emit-rtl.c
gcc/expr.c
gcc/flags.h
gcc/toplev.c
gcc/tree.def

index 99c8a602bbb6a3972c33bf37721b8cf615bbcfa5..cc6a74a5668d2a8d5068d433994f5628a6f9dfd9 100644 (file)
@@ -1995,9 +1995,12 @@ expand_call (exp, target, ignore)
     }
 #endif
 
-  /* Perform all cleanups needed for the arguments of this call
-     (i.e. destructors in C++).  */
-  expand_cleanups_to (old_cleanups);
+  if (flag_short_temps)
+    {
+      /* Perform all cleanups needed for the arguments of this call
+        (i.e. destructors in C++).  */
+      expand_cleanups_to (old_cleanups);
+    }
 
   /* If size of args is variable or this was a constructor call for a stack
      argument, restore saved stack-pointer value.  */
index 607dc8ae35385f40d501b5507e18fd8c73277101..55ee134f07bcfd0dc40bc97c574030ba6edd1212 100644 (file)
@@ -2176,7 +2176,9 @@ delete_insns_since (from)
   last_insn = from;
 }
 
-/* Move a consecutive bunch of insns to a different place in the chain.
+/* This function is deprecated, please use sequences instead.
+
+   Move a consecutive bunch of insns to a different place in the chain.
    The insns to be moved are those between FROM and TO.
    They are moved to a new position after the insn AFTER.
    AFTER must not be FROM or TO or any insn in between.
index 244a84c57eeca497d8e7b867b4b83b170bac848e..38789ffecc98b768ebe7b305743569d90abb0068 100644 (file)
@@ -179,6 +179,7 @@ static void do_jump_by_parts_equality_rtx PROTO((rtx, rtx, rtx));
 static void do_jump_for_compare        PROTO((rtx, rtx, rtx));
 static rtx compare             PROTO((tree, enum rtx_code, enum rtx_code));
 static rtx do_store_flag       PROTO((tree, rtx, enum machine_mode, int));
+static tree defer_cleanups_to  PROTO((tree));
 
 /* Record for each mode whether we can move a register directly to or
    from an object of that mode in memory.  If we can't, we won't try
@@ -3535,6 +3536,9 @@ safe_from_p (x, exp)
          exp_rtl = RTL_EXPR_RTL (exp);
          break;
 
+       case CLEANUP_POINT_EXPR:
+         return safe_from_p (x, TREE_OPERAND (exp, 0));
+
        case SAVE_EXPR:
          exp_rtl = SAVE_EXPR_RTL (exp);
          break;
@@ -4609,6 +4613,14 @@ expand_expr (exp, target, tmode, modifier)
        }
       return RTL_EXPR_RTL (exp);
 
+    case CLEANUP_POINT_EXPR:
+      {
+       tree old_cleanups = cleanups_this_call;
+       op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, modifier);
+       expand_cleanups_to (old_cleanups);
+      }
+      return op0;
+
     case CALL_EXPR:
       /* Check for a built-in function.  */
       if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
@@ -5295,6 +5307,17 @@ expand_expr (exp, target, tmode, modifier)
 
     case COND_EXPR:
       {
+       rtx flag = NULL_RTX;
+       tree left_cleanups = NULL_TREE;
+       tree right_cleanups = NULL_TREE;
+
+       /* Used to save a pointer to the place to put the setting of
+          the flag that indicates if this side of the conditional was
+          taken.  We backpatch the code, if we find out later that we
+          have any conditional cleanups that need to be performed. */
+       rtx dest_right_flag = NULL_RTX;
+       rtx dest_left_flag = NULL_RTX;
+
        /* Note that COND_EXPRs whose type is a structure or union
           are required to be constructed to contain assignments of
           a temporary variable, so that we can evaluate them here
@@ -5306,7 +5329,6 @@ expand_expr (exp, target, tmode, modifier)
        tree singleton = 0;
        tree binary_op = 0, unary_op = 0;
        tree old_cleanups = cleanups_this_call;
-       cleanups_this_call = 0;
 
        /* If this is (A ? 1 : 0) and A is a condition, just evaluate it and
           convert it to our mode, if necessary.  */
@@ -5430,6 +5452,7 @@ expand_expr (exp, target, tmode, modifier)
        NO_DEFER_POP;
        op0 = gen_label_rtx ();
 
+       flag = gen_reg_rtx (word_mode);
        if (singleton && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)))
          {
            if (temp != 0)
@@ -5448,16 +5471,14 @@ expand_expr (exp, target, tmode, modifier)
            else
              expand_expr (singleton,
                           ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
-           if (cleanups_this_call)
-             {
-               sorry ("aggregate value in COND_EXPR");
-               cleanups_this_call = 0;
-             }
+           dest_left_flag = get_last_insn ();
            if (singleton == TREE_OPERAND (exp, 1))
              jumpif (TREE_OPERAND (exp, 0), op0);
            else
              jumpifnot (TREE_OPERAND (exp, 0), op0);
 
+           /* Allows cleanups up to here. */
+           old_cleanups = cleanups_this_call;
            if (binary_op && temp == 0)
              /* Just touch the other operand.  */
              expand_expr (TREE_OPERAND (binary_op, 1),
@@ -5472,6 +5493,7 @@ expand_expr (exp, target, tmode, modifier)
                                  make_tree (type, temp)),
                          temp, 0);
            op1 = op0;
+           dest_right_flag = get_last_insn ();
          }
 #if 0
        /* This is now done in jump.c and is better done there because it
@@ -5498,9 +5520,14 @@ expand_expr (exp, target, tmode, modifier)
            if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER)
              temp = gen_reg_rtx (mode);
            store_expr (TREE_OPERAND (exp, 2), temp, 0);
+           dest_left_flag = get_last_insn ();
            jumpifnot (TREE_OPERAND (exp, 0), op0);
+
+           /* Allows cleanups up to here. */
+           old_cleanups = cleanups_this_call;
            store_expr (TREE_OPERAND (exp, 1), temp, 0);
            op1 = op0;
+           dest_right_flag = get_last_insn ();
          }
 #endif
        /* Check for A op 0 ? A : FOO and A op 0 ? FOO : A where OP is any
@@ -5518,9 +5545,14 @@ expand_expr (exp, target, tmode, modifier)
            if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER)
              temp = gen_reg_rtx (mode);
            store_expr (TREE_OPERAND (exp, 1), temp, 0);
+           dest_left_flag = get_last_insn ();
            jumpif (TREE_OPERAND (exp, 0), op0);
+
+           /* Allows cleanups up to here. */
+           old_cleanups = cleanups_this_call;
            store_expr (TREE_OPERAND (exp, 2), temp, 0);
            op1 = op0;
+           dest_right_flag = get_last_insn ();
          }
        else if (temp
                 && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<'
@@ -5533,24 +5565,31 @@ expand_expr (exp, target, tmode, modifier)
            if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER)
              temp = gen_reg_rtx (mode);
            store_expr (TREE_OPERAND (exp, 2), temp, 0);
+           dest_left_flag = get_last_insn ();
            jumpifnot (TREE_OPERAND (exp, 0), op0);
+
+           /* Allows cleanups up to here. */
+           old_cleanups = cleanups_this_call;
            store_expr (TREE_OPERAND (exp, 1), temp, 0);
            op1 = op0;
+           dest_right_flag = get_last_insn ();
          }
        else
          {
            op1 = gen_label_rtx ();
            jumpifnot (TREE_OPERAND (exp, 0), op0);
+
+           /* Allows cleanups up to here. */
+           old_cleanups = cleanups_this_call;
            if (temp != 0)
              store_expr (TREE_OPERAND (exp, 1), temp, 0);
            else
              expand_expr (TREE_OPERAND (exp, 1),
                           ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
-           if (cleanups_this_call)
-             {
-               sorry ("aggregate value in COND_EXPR");
-               cleanups_this_call = 0;
-             }
+           dest_left_flag = get_last_insn ();
+
+           /* Handle conditional cleanups, if any. */
+           left_cleanups = defer_cleanups_to (old_cleanups);
 
            emit_queue ();
            emit_jump_insn (gen_jump (op1));
@@ -5561,18 +5600,58 @@ expand_expr (exp, target, tmode, modifier)
            else
              expand_expr (TREE_OPERAND (exp, 2),
                           ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
+           dest_right_flag = get_last_insn ();
          }
 
-       if (cleanups_this_call)
-         {
-           sorry ("aggregate value in COND_EXPR");
-           cleanups_this_call = 0;
-         }
+       /* Handle conditional cleanups, if any. */
+       right_cleanups = defer_cleanups_to (old_cleanups);
 
        emit_queue ();
        emit_label (op1);
        OK_DEFER_POP;
-       cleanups_this_call = old_cleanups;
+
+       /* Add back in, any conditional cleanups. */
+       if (left_cleanups || right_cleanups)
+         {
+           tree new_cleanups;
+           tree cond;
+           rtx last;
+
+           /* Now that we know that a flag is needed, go back and add in the
+              setting of the flag. */
+
+           /* Do the left side flag. */
+           last = get_last_insn ();
+           /* Flag left cleanups as needed. */
+           emit_move_insn (flag, const1_rtx);
+           /* ??? deprecated, use sequences instead.  */
+           reorder_insns (NEXT_INSN (last), get_last_insn (), dest_left_flag);
+
+           /* Do the right side flag. */
+           last = get_last_insn ();
+           /* Flag left cleanups as needed. */
+           emit_move_insn (flag, const0_rtx);
+           /* ??? deprecated, use sequences instead.  */
+           reorder_insns (NEXT_INSN (last), get_last_insn (), dest_right_flag);
+
+           /* convert flag, which is an rtx, into a tree. */
+           cond = make_node (RTL_EXPR);
+           TREE_TYPE (cond) = integer_type_node;
+           RTL_EXPR_RTL (cond) = flag;
+           RTL_EXPR_SEQUENCE (cond) = NULL_RTX;
+
+           if (! left_cleanups)
+             left_cleanups = integer_zero_node;
+           if (! right_cleanups)
+             right_cleanups = integer_zero_node;
+           new_cleanups = build (COND_EXPR, void_type_node, cond,
+                                 left_cleanups, right_cleanups);
+           new_cleanups = fold (new_cleanups);
+
+           /* Now add in the conditionalized cleanups. */
+           cleanups_this_call
+             = tree_cons (NULL_TREE, new_cleanups, cleanups_this_call);
+         }
        return temp;
       }
 
@@ -8170,6 +8249,45 @@ do_pending_stack_adjust ()
     }
 }
 
+/* Defer the expansion all cleanups up to OLD_CLEANUPS.
+   Returns the cleanups to be performed.  */
+
+static tree
+defer_cleanups_to (old_cleanups)
+     tree old_cleanups;
+{
+  tree new_cleanups = NULL_TREE;
+  tree cleanups = cleanups_this_call;
+  tree last = NULL_TREE;
+
+  while (cleanups_this_call != old_cleanups)
+    {
+      cleanups_this_call = TREE_CHAIN (cleanups_this_call);
+    }      
+
+  if (last)
+    {
+      /* Remove the list from the chain of cleanups.  */
+      TREE_CHAIN (last) = NULL_TREE;
+
+      /* reverse them so that we can build them in the right order.  */
+      cleanups = nreverse (cleanups);
+
+      while (cleanups)
+       {
+         if (new_cleanups)
+           new_cleanups = build (COMPOUND_EXPR, TREE_TYPE (new_cleanups),
+                                 TREE_VALUE (cleanups), new_cleanups);
+         else
+           new_cleanups = TREE_VALUE (cleanups);
+
+         cleanups = TREE_CHAIN (cleanups);
+       }
+    }
+
+  return new_cleanups;
+}
+
 /* Expand all cleanups up to OLD_CLEANUPS.
    Needed here, and also for language-dependent calls.  */
 
index 128b27f15ecc82666fbc088e1743b1f99ef79a80..07ea73490eec0e4624cda0f2fa054c69d60ee6ae 100644 (file)
@@ -294,6 +294,10 @@ extern int flag_schedule_insns_after_reload;
 
 extern int flag_delayed_branch;
 
+/* Nonzero means to run cleanups after CALL_EXPRs. */
+
+extern int flag_short_temps;
+
 /* Nonzero means pretend it is OK to examine bits of target floats,
    even if that isn't true.  The resulting code will have incorrect constants,
    but the same series of instructions that the native compiler would make.  */
index 96a01adb386c464d57cab3d1e155acaf8cee47f0..ec0baa4abdd2bc32b15c613fecc60808201e2d41 100644 (file)
@@ -448,6 +448,10 @@ int flag_shared_data;
 
 int flag_delayed_branch;
 
+/* Nonzero means to run cleanups after CALL_EXPRs.  */
+
+int flag_short_temps;
+
 /* Nonzero if we are compiling pure (sharable) code.
    Value is 1 if we are doing reasonable (i.e. simple
    offset into offset table) pic.  Value is 2 if we can
@@ -666,6 +670,8 @@ char *lang_options[] =
   "-fno-nonnull-objects",
   "-fsave-memoized",
   "-fno-save-memoized",
+  "-fshort-temps",
+  "-fno-short-temps",
   "-fstats",
   "-fno-stats",
   "-fstrict-prototype",
index 7eb9a2e09513e95469a2206a73f205f4ffafe09f..71d638640eb6a46a5195cc941135a6c09d4c2d48 100644 (file)
@@ -436,10 +436,16 @@ DEFTREECODE (METHOD_CALL_EXPR, "method_call_expr", "e", 4)
    Operand 2 is the cleanup expression for the object.
      The RTL_EXPR is used in this expression, which is how the expression
      manages to act on the proper value.
-   The cleanup is executed when the value is no longer needed,
-   which is not at precisely the same time that this value is computed.  */
+   The cleanup is executed by the first enclosing CLEANUP_POINT_EXPR, if
+   it exists, otherwise it is the responsibility of the caller to manually
+   call expand_cleanups_to, as needed.  */
 DEFTREECODE (WITH_CLEANUP_EXPR, "with_cleanup_expr", "e", 3)
 
+/* Specify a cleanup point.
+   Operand 0 is the expression that has cleanups that we want ensure are
+   cleaned up.  */
+DEFTREECODE (CLEANUP_POINT_EXPR, "cleanup_point_expr", "e", 1)
+
 /* The following two codes are used in languages that have types where
    the position and/or sizes of fields vary from object to object of the
    same type, i.e., where some other field in the object contains a value