tree-def (WITH_SIZE_EXPR): New.
authorRichard Henderson <rth@redhat.com>
Fri, 16 Jul 2004 21:13:08 +0000 (14:13 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 16 Jul 2004 21:13:08 +0000 (14:13 -0700)
        * tree-def (WITH_SIZE_EXPR): New.
        * explow.c (expr_size, int_expr_size): Handle WITH_SIZE_EXPR.
        * expr.c (expand_expr_real_1): Likewise.
        * gimplify.c (maybe_with_size_expr): New.
        (gimplify_arg, gimplify_modify_expr): Use it.
        (gimplify_modify_expr_to_memcpy): Take size parameter.
        (gimplify_modify_expr_to_memset): Likewise.
        (gimplify_expr): Handle WITH_SIZE_EXPR.
        * tree-alias-common.c (find_func_aliases): Likewise.
        * tree-eh.c (tree_could_trap_p): Likewise.
        (tree_could_throw_p): Likewise.
        * tree-gimple.c (is_gimple_lvalue): Likewise.
        (get_call_expr_in): Likewise.
        * tree-inline.c (estimate_num_insns_1): Likewise.
        (expand_calls_inline): Likewise.
        * tree-nested.c (convert_call_expr): Likewise.
        * tree-pretty-print.c (dump_generic_node): Likewise.
        * tree-sra.c (sra_walk_expr): Likewise.
        * tree-ssa-alias.c (add_pointed_to_expr): Likewise.
        * tree-ssa-ccp.c (get_rhs, set_rhs): Likewise.
        * tree-ssa-operands.c (get_expr_operands): Likewise.
        * tree-tailcall.c (find_tail_calls): Likewise.

        * calls.c (expand_call): Reset old_stack_allocated after
        calling emit_stack_restore.

        * gcc.c-torture/compile/20020210-1.c: Remove XFAIL.

From-SVN: r84833

19 files changed:
gcc/ChangeLog
gcc/calls.c
gcc/explow.c
gcc/expr.c
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/20020210-1.c
gcc/tree-alias-common.c
gcc/tree-eh.c
gcc/tree-gimple.c
gcc/tree-inline.c
gcc/tree-nested.c
gcc/tree-pretty-print.c
gcc/tree-sra.c
gcc/tree-ssa-alias.c
gcc/tree-ssa-ccp.c
gcc/tree-ssa-operands.c
gcc/tree-tailcall.c
gcc/tree.def

index 054c04ab6cca3315df9eac441bddd9f89fa4aed6..2647e885fe958cc72b1911ae2a518635d5bf5a22 100644 (file)
@@ -1,3 +1,31 @@
+2004-07-16  Richard Henderson  <rth@redhat.com>
+
+       * tree-def (WITH_SIZE_EXPR): New.
+       * explow.c (expr_size, int_expr_size): Handle WITH_SIZE_EXPR.
+       * expr.c (expand_expr_real_1): Likewise.
+       * gimplify.c (maybe_with_size_expr): New.
+       (gimplify_arg, gimplify_modify_expr): Use it.
+       (gimplify_modify_expr_to_memcpy): Take size parameter.
+       (gimplify_modify_expr_to_memset): Likewise.
+       (gimplify_expr): Handle WITH_SIZE_EXPR.
+       * tree-alias-common.c (find_func_aliases): Likewise.
+       * tree-eh.c (tree_could_trap_p): Likewise.
+       (tree_could_throw_p): Likewise.
+       * tree-gimple.c (is_gimple_lvalue): Likewise.
+       (get_call_expr_in): Likewise.
+       * tree-inline.c (estimate_num_insns_1): Likewise.
+       (expand_calls_inline): Likewise.
+       * tree-nested.c (convert_call_expr): Likewise.
+       * tree-pretty-print.c (dump_generic_node): Likewise.
+       * tree-sra.c (sra_walk_expr): Likewise.
+       * tree-ssa-alias.c (add_pointed_to_expr): Likewise.
+       * tree-ssa-ccp.c (get_rhs, set_rhs): Likewise.
+       * tree-ssa-operands.c (get_expr_operands): Likewise.
+       * tree-tailcall.c (find_tail_calls): Likewise.
+       
+       * calls.c (expand_call): Reset old_stack_allocated after
+       calling emit_stack_restore.
+
 2004-07-16  Richard Henderson  <rth@redhat.com>
 
        * langhooks-def.h (LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING,
index 231d69b0aff322c7fa72bf757d41d6187df454a4..c48fd8299e839e93ce50472d593c51e6a5ce549d 100644 (file)
@@ -3045,6 +3045,7 @@ expand_call (tree exp, rtx target, int ignore)
          emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
          stack_pointer_delta = old_stack_pointer_delta;
          pending_stack_adjust = old_pending_adj;
+         old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
          stack_arg_under_construction = old_stack_arg_under_construction;
          highest_outgoing_arg_in_use = initial_highest_arg_in_use;
          stack_usage_map = initial_stack_usage_map;
index 54a863501ea07e0854b0fd500f85203de7312c2f..3fb0f94f423d694937965f2c8c8619a7f7953c0d 100644 (file)
@@ -240,7 +240,12 @@ eliminate_constant_term (rtx x, rtx *constptr)
 rtx
 expr_size (tree exp)
 {
-  tree size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp);
+  tree size;
+
+  if (TREE_CODE (exp) == WITH_SIZE_EXPR)
+    size = TREE_OPERAND (exp, 1);
+  else
+    size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp);
 
   return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
 }
@@ -251,17 +256,17 @@ expr_size (tree exp)
 HOST_WIDE_INT
 int_expr_size (tree exp)
 {
-  tree t = lang_hooks.expr_size (exp);
-
-  if (t == 0
-      || TREE_CODE (t) != INTEGER_CST
-      || TREE_OVERFLOW (t)
-      || TREE_INT_CST_HIGH (t) != 0
-      /* If the result would appear negative, it's too big to represent.  */
-      || (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0)
+  tree size;
+
+  if (TREE_CODE (exp) == WITH_SIZE_EXPR)
+    size = TREE_OPERAND (exp, 1);
+  else
+    size = lang_hooks.expr_size (exp);
+
+  if (size == 0 || !host_integerp (size, 0))
     return -1;
 
-  return TREE_INT_CST_LOW (t);
+  return tree_low_cst (size, 0);
 }
 \f
 /* Return a copy of X in which all memory references
index 302c4ee1607f741df0d67f259759e1fe443cc0f0..dd1aad9cc329727517f9b9679605c1777a69a933 100644 (file)
@@ -8651,6 +8651,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       expand_asm_expr (exp);
       return const0_rtx;
 
+    case WITH_SIZE_EXPR:
+      /* WITH_SIZE_EXPR expands to its first argument.  The caller should
+        have pulled out the size to use in whatever context it needed.  */
+      return expand_expr_real (TREE_OPERAND (exp, 0), original_target, tmode,
+                              modifier, alt_rtl);
+
     default:
       return lang_hooks.expand_expr (exp, original_target, tmode,
                                     modifier, alt_rtl);
index 642cff9b81eccaa4e6478f1549851959f189ab48..6cf5d486b3f261c1db676ac4fc994186c09eaec5 100644 (file)
@@ -72,8 +72,6 @@ typedef struct gimple_temp_hash_elt
 } elt_t;
 
 /* Forward declarations.  */
-static enum gimplify_status gimplify_modify_expr_rhs (tree *, tree *, tree *,
-                                                     tree *, tree *, bool);
 static enum gimplify_status gimplify_compound_expr (tree *, tree *, bool);
 
 
@@ -1788,6 +1786,27 @@ gimplify_self_mod_expr (tree *expr_p, tree *pre_p, tree *post_p,
     }
 }
 
+/* If *EXPR_P has a variable sized type, wrap it in a WITH_SIZE_EXPR.  */
+
+static void
+maybe_with_size_expr (tree *expr_p)
+{
+  tree expr, type, size;
+
+  expr = *expr_p;
+  type = TREE_TYPE (expr);
+  if (type == error_mark_node)
+    return;
+
+  size = TYPE_SIZE_UNIT (type);
+  if (size && TREE_CODE (size) != INTEGER_CST)
+    {
+      size = unshare_expr (size);
+      size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, expr);
+      *expr_p = build2 (WITH_SIZE_EXPR, type, expr, size);
+    }
+}
+
 /* Subroutine of gimplify_call_expr:  Gimplify a single argument.  */
 
 static enum gimplify_status
@@ -1806,6 +1825,9 @@ gimplify_arg (tree *expr_p, tree *pre_p)
   else
     test = is_gimple_lvalue, fb = fb_either;
 
+  /* If this is a variable sized type, we must remember the size.  */
+  maybe_with_size_expr (expr_p);
+
   /* There is a sequence point before a function call.  Side effects in
      the argument list must occur before the actual call. So, when
      gimplifying arguments, force gimplify_expr to use an internal
@@ -2316,18 +2338,14 @@ gimplify_cond_expr (tree *expr_p, tree *pre_p, tree target)
    a call to __builtin_memcpy.  */
 
 static enum gimplify_status
-gimplify_modify_expr_to_memcpy (tree *expr_p, bool want_value)
+gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value)
 {
   tree args, t, to, to_ptr, from;
 
   to = TREE_OPERAND (*expr_p, 0);
   from = TREE_OPERAND (*expr_p, 1);
 
-  t = TYPE_SIZE_UNIT (TREE_TYPE (from));
-  t = unshare_expr (t);
-  t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, to);
-  t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, from);
-  args = tree_cons (NULL, t, NULL);
+  args = tree_cons (NULL, size, NULL);
 
   t = build_fold_addr_expr (from);
   args = tree_cons (NULL, t, args);
@@ -2352,16 +2370,13 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, bool want_value)
    a CONSTRUCTOR with an empty element list.  */
 
 static enum gimplify_status
-gimplify_modify_expr_to_memset (tree *expr_p, bool want_value)
+gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value)
 {
   tree args, t, to, to_ptr;
 
   to = TREE_OPERAND (*expr_p, 0);
 
-  t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (*expr_p, 1)));
-  t = unshare_expr (t);
-  t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, to);
-  args = tree_cons (NULL, t, NULL);
+  args = tree_cons (NULL, size, NULL);
 
   args = tree_cons (NULL, integer_zero_node, args);
 
@@ -2771,24 +2786,13 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
   if (ret != GS_UNHANDLED)
     return ret;
 
-  /* If the value being copied is of variable width, expose the length
-     if the copy by converting the whole thing to a memcpy/memset.
-     Note that we need to do this before gimplifying any of the operands
-     so that we can resolve any PLACEHOLDER_EXPRs in the size. 
-     Also note that the RTL expander uses the size of the expression to
-     be copied, not of the destination, so that is what we must here.
-     The types on both sides of the MODIFY_EXPR should be the same,
-     but they aren't always and there are problems with class-wide types
-     in Ada where it's hard to make it "correct".  */
-  if (TREE_CODE (TREE_TYPE (*from_p)) != ERROR_MARK
-      && TYPE_SIZE_UNIT (TREE_TYPE (*from_p))
-      && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*from_p))) != INTEGER_CST)
-    {
-      if (TREE_CODE (*from_p) == CONSTRUCTOR)
-       return gimplify_modify_expr_to_memset (expr_p, want_value);
-      else
-       return gimplify_modify_expr_to_memcpy (expr_p, want_value);
-    }
+  /* If the value being copied is of variable width, compute the length
+     of the copy into a WITH_SIZE_EXPR.   Note that we need to do this
+     before gimplifying any of the operands so that we can resolve any
+     PLACEHOLDER_EXPRs in the size.  Also note that the RTL expander uses
+     the size of the expression to be copied, not of the destination, so
+     that is what we must here.  */
+  maybe_with_size_expr (from_p);
 
   ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
   if (ret == GS_ERROR)
@@ -2805,6 +2809,23 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
   if (ret != GS_UNHANDLED)
     return ret;
 
+  /* If we've got a variable sized assignment between two lvalues (i.e. does
+     not involve a call), then we can make things a bit more straightforward
+     by converting the assignment to memcpy or memset.  */
+  if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
+    {
+      tree from = TREE_OPERAND (*from_p, 0);
+      tree size = TREE_OPERAND (*from_p, 1);
+
+      if (TREE_CODE (from) == CONSTRUCTOR)
+       return gimplify_modify_expr_to_memset (expr_p, size, want_value);
+      if (is_gimple_addr_expr_arg (from))
+       {
+         *from_p = from;
+         return gimplify_modify_expr_to_memcpy (expr_p, size, want_value);
+       }
+    }
+
   /* If the destination is already simple, nothing else needed.  */
   if (is_gimple_tmp_var (*to_p) || !want_value)
     ret = GS_ALL_DONE;
@@ -3784,6 +3805,17 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
          ret = gimplify_statement_list (expr_p);
          break;
 
+       case WITH_SIZE_EXPR:
+         {
+           enum gimplify_status r0, r1;
+           r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, 
+                               post_p == &internal_post ? NULL : post_p,
+                               gimple_test_f, fallback);
+           r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
+                               is_gimple_val, fb_rvalue);
+         }
+         break;
+
        case VAR_DECL:
          /* ??? If this is a local variable, and it has not been seen in any
             outer BIND_EXPR, then it's probably the result of a duplicate
index 83f28398a7a0bd6a3064bbe5f6a9ca0124784c84..bdf36eaea29ac88b4e213bc75845869bf260237a 100644 (file)
@@ -1,3 +1,7 @@
+2004-07-16  Richard Henderson  <rth@redhat.com>
+
+       * gcc.c-torture/compile/20020210-1.c: Remove XFAIL.
+
 2004-07-16  Tobias Schlueter  <tobias.schlueter@physik.uni-muenchen.de>
 
        * lib/fortran-torture.exp (fortran-torture): Don't test compile
index 960e3d54d8a269a0599a4bbec6c292f4633a73ad..5ca27f4f6ca46b3edd930315f18ae6c67e9f002f 100644 (file)
@@ -1,3 +1,2 @@
 /* PR c/5615 */
-/* { dg-xfail-if "regression/16417" { "*-*-*" } { "-O1" "-O2" "-O3 -fomit-frame-pointer" "-O3 -g" "-Os" } { "" } } */
 void f(int a, struct {int b[a];} c) {}
index 790d70aa79f19d7594c67059672cb85ee0b0bcc3..a7ce22d8782f8477faec816c9f2ad629383c692e 100644 (file)
@@ -448,7 +448,10 @@ find_func_aliases (tree stp)
        {
          op0 = TREE_OPERAND (stp, 0);
          op1 = TREE_OPERAND (stp, 1);
+         if (TREE_CODE (op1) == WITH_SIZE_EXPR)
+           op1 = TREE_OPERAND (op1, 0);
        }
+
       /* lhsAV should always have an alias variable */
       lhsAV = get_alias_var (op0);
       if (!lhsAV)
index b0638c001084b75d5e683472f15a02103bb044f5..b7fe64de5edc308d28443eba13e9e9b526246138 100644 (file)
@@ -1723,14 +1723,17 @@ tree_could_trap_p (tree expr)
        honor_trapv = true;
     }
 
+ restart:
   switch (code)
     {
     case COMPONENT_REF:
     case REALPART_EXPR:
     case IMAGPART_EXPR:
     case BIT_FIELD_REF:
-      t = TREE_OPERAND (expr, 0);
-      return tree_could_trap_p (t);
+    case WITH_SIZE_EXPR:
+      expr = TREE_OPERAND (expr, 0);
+      code = TREE_CODE (expr);
+      goto restart;
 
     case ARRAY_RANGE_REF:
       /* Let us be conservative here for now.  We might be checking bounds of
@@ -1843,6 +1846,8 @@ tree_could_throw_p (tree t)
       t = TREE_OPERAND (t, 1);
     }
 
+  if (TREE_CODE (t) == WITH_SIZE_EXPR)
+    t = TREE_OPERAND (t, 0);
   if (TREE_CODE (t) == CALL_EXPR)
     return (call_expr_flags (t) & ECF_NOTHROW) == 0;
   if (flag_non_call_exceptions)
index 193f093a8e34d290144d58512d77cbac8b8c5342..c081b5aabaed4910de27ec5110c1e844a2457bc5 100644 (file)
@@ -118,12 +118,22 @@ Boston, MA 02111-1307, USA.  */
    addr-expr-arg: ID
                | compref
 
+   with-size-arg: addr-expr-arg
+               | indirectref
+               | call-stmt
+
+   indirectref : INDIRECT_REF
+                       op0 -> val
+
    lhs         : addr-expr-arg
-               | '*' val
                | bitfieldref
+               | indirectref
+               | WITH_SIZE_EXPR
+                       op0 -> with-size-arg
+                       op1 -> val
 
    min-lval    : ID
-               | '*' val
+               | indirectref
 
    bitfieldref : BIT_FIELD_REF
                        op0 -> inner-compref
@@ -155,18 +165,26 @@ Boston, MA 02111-1307, USA.  */
                        op0 -> inner-compref
 
    condition   : val
-               | val RELOP val
+               | RELOP
+                       op0 -> val
+                       op1 -> val
 
    val         : ID
                | CONST
 
    rhs         : lhs
                | CONST
-               | '&' addr-expr-arg
-               | call_expr
-               | UNOP val
-               | val BINOP val
-               | val RELOP val
+               | call-stmt
+               | ADDR_EXPR
+                       op0 -> addr-expr-arg
+               | UNOP
+                       op0 -> val
+               | BINOP
+                       op0 -> val
+                       op1 -> val
+               | RELOP
+                       op0 -> val
+                       op1 -> val
 */
 
 static inline bool is_gimple_id (tree);
@@ -286,6 +304,7 @@ is_gimple_lvalue (tree t)
 {
   return (is_gimple_addr_expr_arg (t)
          || TREE_CODE (t) == INDIRECT_REF
+         || TREE_CODE (t) == WITH_SIZE_EXPR
          /* These are complex lvalues, but don't have addresses, so they
             go here.  */
          || TREE_CODE (t) == BIT_FIELD_REF);
@@ -506,6 +525,8 @@ get_call_expr_in (tree t)
 {
   if (TREE_CODE (t) == MODIFY_EXPR)
     t = TREE_OPERAND (t, 1);
+  if (TREE_CODE (t) == WITH_SIZE_EXPR)
+    t = TREE_OPERAND (t, 0);
   if (TREE_CODE (t) == CALL_EXPR)
     return t;
   return NULL_TREE;
index 705216adb4f6e03b4063d1d57f45d588a798d1a8..edd5faece9536bb45d535794b4b14089c897dd1e 100644 (file)
@@ -1262,6 +1262,7 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
     case EXIT_EXPR:
     case LOOP_EXPR:
     case PHI_NODE:
+    case WITH_SIZE_EXPR:
       break;
 
     /* We don't account constants for now.  Assume that the cost is amortized
@@ -1779,6 +1780,11 @@ expand_calls_inline (tree *stmt_p, inline_data *id)
     case MODIFY_EXPR:
       stmt_p = &TREE_OPERAND (stmt, 1);
       stmt = *stmt_p;
+      if (TREE_CODE (stmt) == WITH_SIZE_EXPR)
+       {
+         stmt_p = &TREE_OPERAND (stmt, 0);
+         stmt = *stmt_p;
+       }
       if (TREE_CODE (stmt) != CALL_EXPR)
        break;
 
index fdcaaf82436ebb48f844cd970e775e05fd8956aa..16db5cf815737af0b259718f44291e36bba9d296 100644 (file)
@@ -1196,7 +1196,8 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data)
 
     case RETURN_EXPR:
     case MODIFY_EXPR:
-      /* Only return and modify may contain calls.  */
+    case WITH_SIZE_EXPR:
+      /* Only return modify and with_size_expr may contain calls.  */
       *walk_subtrees = 1;
       break;
 
index 65d362a25bf2c74edcfd5fcb3161f2c34680c8d4..c187b1a8696060783a898f1f8fd21fc82bcfa8f1 100644 (file)
@@ -1413,6 +1413,14 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
       pp_decimal_int (buffer, SSA_NAME_VERSION (node));
       break;
 
+    case WITH_SIZE_EXPR:
+      pp_string (buffer, "WITH_SIZE_EXPR <");
+      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+      pp_string (buffer, ", ");
+      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
+      pp_string (buffer, ">");
+      break;
+
     case VALUE_HANDLE:
       pp_printf (buffer, "VH.%d", VALUE_HANDLE_ID (node));
       break;
index 423ee3ca498f5c282bb21ade93def3a215d96cf9..73866b4972a2f4fc2b9a633098d4abd40bc706fa 100644 (file)
@@ -731,6 +731,11 @@ sra_walk_expr (tree *expr_p, block_stmt_iterator *bsi, bool is_output,
           type other than the one we've scalarized.  */
        goto use_all;
 
+      case WITH_SIZE_EXPR:
+       /* This is a transparent wrapper.  The entire inner expression really
+          is being used.  */
+       goto use_all;
+
       use_all:
         expr_p = &TREE_OPERAND (inner, 0);
        inner = expr = *expr_p;
index 0d96b16aa8318d06d8b7f297fd16dbcc053e8867..ed4ffd993e32b06e157fc75639c518508d99a312 100644 (file)
@@ -1680,6 +1680,9 @@ add_pointed_to_expr (tree ptr, tree value)
 {
   struct ptr_info_def *pi;
 
+  if (TREE_CODE (value) == WITH_SIZE_EXPR)
+    value = TREE_OPERAND (value, 0);
+
 #if defined ENABLE_CHECKING
   /* Pointer variables should have been handled by merge_pointed_to_info.  */
   if (TREE_CODE (value) == SSA_NAME
index 7f28a9f9e93b5ff1b28e871aca271fe85deca845..0c35717531d375325f8262dff3d9ed54efa8ce8f 100644 (file)
@@ -2085,13 +2085,16 @@ get_rhs (tree stmt)
     {
     case RETURN_EXPR:
       stmt = TREE_OPERAND (stmt, 0);
-      if (stmt)
-       return get_rhs (stmt);
-      else
-       return NULL;
+      if (!stmt || TREE_CODE (stmt) != MODIFY_EXPR)
+       return stmt;
+      /* FALLTHRU */
 
     case MODIFY_EXPR:
-      return TREE_OPERAND (stmt, 1);
+      stmt = TREE_OPERAND (stmt, 1);
+      if (TREE_CODE (stmt) == WITH_SIZE_EXPR)
+       return TREE_OPERAND (stmt, 0);
+      else
+       return stmt;
 
     case COND_EXPR:
       return COND_EXPR_COND (stmt);
@@ -2143,6 +2146,9 @@ set_rhs (tree *stmt_p, tree expr)
       /* FALLTHRU */
 
     case MODIFY_EXPR:
+      op = TREE_OPERAND (stmt, 1);
+      if (TREE_CODE (op) == WITH_SIZE_EXPR)
+       stmt = op;
       TREE_OPERAND (stmt, 1) = expr;
       break;
 
index af21f12a4154c7a3cd3ed67836b56a4bb17786b5..bb60bd87332329aa14fcbbc0870f459395b0a6d2 100644 (file)
@@ -931,23 +931,38 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops)
        get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none, prev_vops);
       return;
 
+    case WITH_SIZE_EXPR:
+      /* WITH_SIZE_EXPR is a pass-through reference to it's first argument,
+        and an rvalue reference to its second argument.  */
+      get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, prev_vops);
+      get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, prev_vops);
+      return;
+
     case CALL_EXPR:
       get_call_expr_operands (stmt, expr, prev_vops);
       return;
 
     case MODIFY_EXPR:
-      get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, prev_vops);
+      {
+       int subflags;
+       tree op;
+
+       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, prev_vops);
+
+       op = TREE_OPERAND (expr, 0);
+       if (TREE_CODE (op) == WITH_SIZE_EXPR)
+         op = TREE_OPERAND (expr, 0);
+       if (TREE_CODE (op) == ARRAY_REF 
+           || TREE_CODE (op) == COMPONENT_REF
+           || TREE_CODE (op) == REALPART_EXPR
+           || TREE_CODE (op) == IMAGPART_EXPR)
+         subflags = opf_is_def;
+       else
+         subflags = opf_is_def | opf_kill_def;
 
-      if (TREE_CODE (TREE_OPERAND (expr, 0)) == ARRAY_REF 
-          || TREE_CODE (TREE_OPERAND (expr, 0)) == COMPONENT_REF
-         || TREE_CODE (TREE_OPERAND (expr, 0)) == REALPART_EXPR
-         || TREE_CODE (TREE_OPERAND (expr, 0)) == IMAGPART_EXPR)
-        get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_is_def, 
-                          prev_vops);
-      else
-        get_expr_operands (stmt, &TREE_OPERAND (expr, 0), 
-                          opf_is_def | opf_kill_def, prev_vops);
-      return;
+       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), subflags, prev_vops);
+       return;
+      }
 
     case VA_ARG_EXPR:
       /* Mark VA_ARG_EXPR nodes as making volatile references.  FIXME,
index f69bf3449f2654b84d57f8d280840113a6a984df..5a89868dcc135ab8bfefc0ab1a2018dba4a95476 100644 (file)
@@ -384,6 +384,8 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
        {
          ass_var = TREE_OPERAND (stmt, 0);
          call = TREE_OPERAND (stmt, 1);
+         if (TREE_CODE (call) == WITH_SIZE_EXPR)
+           call = TREE_OPERAND (call, 0);
        }
       else
        {
index 8068f266758f6c53e1b4a74a0ec847d9946c54db..65fd479cdb423400caa5711adbceafd401765913 100644 (file)
@@ -885,6 +885,13 @@ DEFTREECODE (VALUE_HANDLE, "value_handle", 'x', 0)
    baseclass of itself or another class.  */
 DEFTREECODE (TREE_BINFO, "tree_binfo", 'x', 0)
 
+/* Records the size for an expression of variable size type.  This is
+   for use in contexts in which we are accessing the entire object,
+   such as for a function call, or block copy.
+   Operand 0 is the real expression.
+   Operand 1 is the size of the type in the expression.  */
+DEFTREECODE (WITH_SIZE_EXPR, "with_size_expr", 'e', 2)
+
 /*
 Local variables:
 mode:c