OSDN Git Service

2007-07-06 H.J. Lu <hongjiu.lu@intel.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-eh.c
index 0820e67..37fce85 100644 (file)
@@ -1,5 +1,5 @@
 /* Exception handling semantics and decomposition for trees.
-   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -15,8 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -57,15 +57,15 @@ using_eh_for_cleanups (void)
 static int
 struct_ptr_eq (const void *a, const void *b)
 {
-  const void * const * x = a;
-  const void * const * y = b;
+  const void * const * x = (const void * const *) a;
+  const void * const * y = (const void * const *) b;
   return *x == *y;
 }
 
 static hashval_t
 struct_ptr_hash (const void *a)
 {
-  const void * const * x = a;
+  const void * const * x = (const void * const *) a;
   return (size_t)*x >> 4;
 }
 
@@ -100,7 +100,7 @@ add_stmt_to_eh_region_fn (struct function *ifun, tree t, int num)
   gcc_assert (num >= 0);
   gcc_assert (TREE_CODE (t) != RESX_EXPR);
 
-  n = ggc_alloc (sizeof (*n));
+  n = GGC_NEW (struct throw_stmt_node);
   n->stmt = t;
   n->region_nr = num;
 
@@ -112,12 +112,6 @@ add_stmt_to_eh_region_fn (struct function *ifun, tree t, int num)
   slot = htab_find_slot (get_eh_throw_stmt_table (ifun), n, INSERT);
   gcc_assert (!*slot);
   *slot = n;
-  /* ??? For the benefit of calls.c, converting all this to rtl,
-     we need to record the call expression, not just the outer
-     modify statement.  */
-  if (TREE_CODE (t) == MODIFY_EXPR
-      && (t = get_call_expr_in (t)))
-    add_stmt_to_eh_region_fn (ifun, t, num);
 }
 
 void
@@ -141,12 +135,6 @@ remove_stmt_from_eh_region_fn (struct function *ifun, tree t)
   if (slot)
     {
       htab_clear_slot (get_eh_throw_stmt_table (ifun), slot);
-      /* ??? For the benefit of calls.c, converting all this to rtl,
-        we need to record the call expression, not just the outer
-        modify statement.  */
-      if (TREE_CODE (t) == MODIFY_EXPR
-         && (t = get_call_expr_in (t)))
-       remove_stmt_from_eh_region_fn (ifun, t);
       return true;
     }
   else
@@ -168,7 +156,8 @@ lookup_stmt_eh_region_fn (struct function *ifun, tree t)
     return -2;
 
   n.stmt = t;
-  p = htab_find (get_eh_throw_stmt_table (ifun), &n);
+  p = (struct throw_stmt_node *) htab_find (get_eh_throw_stmt_table (ifun),
+                                            &n);
 
   return (p ? p->region_nr : -1);
 }
@@ -202,7 +191,7 @@ record_in_finally_tree (tree child, tree parent)
   struct finally_tree_node *n;
   void **slot;
 
-  n = xmalloc (sizeof (*n));
+  n = XNEW (struct finally_tree_node);
   n->child = child;
   n->parent = parent;
 
@@ -266,7 +255,7 @@ outside_finally_tree (tree start, tree target)
   do
     {
       n.child = start;
-      p = htab_find (finally_tree, &n);
+      p = (struct finally_tree_node *) htab_find (finally_tree, &n);
       if (!p)
        return true;
       start = p->parent;
@@ -369,7 +358,8 @@ find_goto_replacement (struct leh_tf_state *tf, tree stmt)
 {
   struct goto_queue_node tmp, *ret;
   tmp.stmt = stmt;
-  ret = bsearch (&tmp, tf->goto_queue, tf->goto_queue_active,
+  ret = (struct goto_queue_node *)
+     bsearch (&tmp, tf->goto_queue, tf->goto_queue_active,
                 sizeof (struct goto_queue_node), goto_queue_cmp);
   return (ret ? ret->repl_stmt : NULL);
 }
@@ -537,7 +527,7 @@ maybe_record_in_goto_queue (struct leh_state *state, tree stmt)
       size = (size ? size * 2 : 32);
       tf->goto_queue_size = size;
       tf->goto_queue
-       = xrealloc (tf->goto_queue, size * sizeof (struct goto_queue_node));
+         = XRESIZEVEC (struct goto_queue_node, tf->goto_queue, size);
     }
 
   q = &tf->goto_queue[active];
@@ -622,10 +612,10 @@ do_return_redirection (struct goto_queue_node *q, tree finlab, tree mod,
          q->cont_stmt = q->stmt;
          break;
 
-       case MODIFY_EXPR:
+       case GIMPLE_MODIFY_STMT:
          {
-           tree result = TREE_OPERAND (ret_expr, 0);
-           tree new, old = TREE_OPERAND (ret_expr, 1);
+           tree result = GIMPLE_STMT_OPERAND (ret_expr, 0);
+           tree new, old = GIMPLE_STMT_OPERAND (ret_expr, 1);
 
            if (!*return_value_p)
              {
@@ -644,13 +634,13 @@ do_return_redirection (struct goto_queue_node *q, tree finlab, tree mod,
            else
              new = *return_value_p;
 
-           x = build (MODIFY_EXPR, TREE_TYPE (new), new, old);
+           x = build_gimple_modify_stmt (new, old);
            append_to_statement_list (x, &q->repl_stmt);
 
            if (new == result)
              x = result;
            else
-             x = build (MODIFY_EXPR, TREE_TYPE (result), result, new);
+             x = build_gimple_modify_stmt (result, new);
            q->cont_stmt = build1 (RETURN_EXPR, void_type_node, x);
          }
 
@@ -839,21 +829,21 @@ honor_protect_cleanup_actions (struct leh_state *outer_state,
       save_filt = create_tmp_var (integer_type_node, "save_filt");
 
       i = tsi_start (finally);
-      x = build (EXC_PTR_EXPR, ptr_type_node);
-      x = build (MODIFY_EXPR, void_type_node, save_eptr, x);
+      x = build0 (EXC_PTR_EXPR, ptr_type_node);
+      x = build_gimple_modify_stmt (save_eptr, x);
       tsi_link_before (&i, x, TSI_CONTINUE_LINKING);
 
-      x = build (FILTER_EXPR, integer_type_node);
-      x = build (MODIFY_EXPR, void_type_node, save_filt, x);
+      x = build0 (FILTER_EXPR, integer_type_node);
+      x = build_gimple_modify_stmt (save_filt, x);
       tsi_link_before (&i, x, TSI_CONTINUE_LINKING);
 
       i = tsi_last (finally);
-      x = build (EXC_PTR_EXPR, ptr_type_node);
-      x = build (MODIFY_EXPR, void_type_node, x, save_eptr);
+      x = build0 (EXC_PTR_EXPR, ptr_type_node);
+      x = build_gimple_modify_stmt (x, save_eptr);
       tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
 
-      x = build (FILTER_EXPR, integer_type_node);
-      x = build (MODIFY_EXPR, void_type_node, x, save_filt);
+      x = build0 (FILTER_EXPR, integer_type_node);
+      x = build_gimple_modify_stmt (x, save_filt);
       tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
 
       x = build_resx (get_eh_region_number (tf->region));
@@ -863,10 +853,10 @@ honor_protect_cleanup_actions (struct leh_state *outer_state,
   /* Wrap the block with protect_cleanup_actions as the action.  */
   if (protect_cleanup_actions)
     {
-      x = build (EH_FILTER_EXPR, void_type_node, NULL, NULL);
+      x = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
       append_to_statement_list (protect_cleanup_actions, &EH_FILTER_FAILURE (x));
       EH_FILTER_MUST_NOT_THROW (x) = 1;
-      finally = build (TRY_CATCH_EXPR, void_type_node, finally, x);
+      finally = build2 (TRY_CATCH_EXPR, void_type_node, finally, x);
       lower_eh_filter (outer_state, &finally);
     }
   else
@@ -1058,14 +1048,14 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
       struct goto_queue_node *q, *qe;
       tree return_val = NULL;
       int return_index, index;
-      struct
+      struct labels_s
       {
        struct goto_queue_node *q;
        tree label;
       } *labels;
 
       return_index = VEC_length (tree, tf->dest_array);
-      labels = xcalloc (sizeof (*labels), return_index + 1);
+      labels = XCNEWVEC (struct labels_s, return_index + 1);
 
       q = tf->goto_queue;
       qe = q + tf->goto_queue_active;
@@ -1163,8 +1153,8 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
   finally_label = create_artificial_label ();
 
   case_label_vec = make_tree_vec (ndests);
-  switch_stmt = build (SWITCH_EXPR, integer_type_node, finally_tmp,
-                      NULL_TREE, case_label_vec);
+  switch_stmt = build3 (SWITCH_EXPR, integer_type_node, finally_tmp,
+                       NULL_TREE, case_label_vec);
   switch_body = NULL;
   last_case = NULL;
   last_case_index = 0;
@@ -1175,8 +1165,9 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
 
   if (tf->may_fallthru)
     {
-      x = build (MODIFY_EXPR, void_type_node, finally_tmp,
-                build_int_cst (NULL_TREE, fallthru_index));
+      x = build_gimple_modify_stmt (finally_tmp,
+                                   build_int_cst (integer_type_node,
+                                                  fallthru_index));
       append_to_statement_list (x, tf->top_p);
 
       if (tf->may_throw)
@@ -1186,13 +1177,13 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
        }
 
 
-      last_case = build (CASE_LABEL_EXPR, void_type_node,
-                        build_int_cst (NULL_TREE, fallthru_index), NULL,
-                        create_artificial_label ());
+      last_case = build3 (CASE_LABEL_EXPR, void_type_node,
+                         build_int_cst (NULL_TREE, fallthru_index), NULL,
+                         create_artificial_label ());
       TREE_VEC_ELT (case_label_vec, last_case_index) = last_case;
       last_case_index++;
 
-      x = build (LABEL_EXPR, void_type_node, CASE_LABEL (last_case));
+      x = build1 (LABEL_EXPR, void_type_node, CASE_LABEL (last_case));
       append_to_statement_list (x, &switch_body);
 
       x = lower_try_finally_fallthru_label (tf);
@@ -1205,17 +1196,18 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
       x = build1 (LABEL_EXPR, void_type_node, tf->eh_label);
       append_to_statement_list (x, tf->top_p);
 
-      x = build (MODIFY_EXPR, void_type_node, finally_tmp,
-                build_int_cst (NULL_TREE, eh_index));
+      x = build_gimple_modify_stmt (finally_tmp,
+                                   build_int_cst (integer_type_node,
+                                                  eh_index));
       append_to_statement_list (x, tf->top_p);
 
-      last_case = build (CASE_LABEL_EXPR, void_type_node,
-                        build_int_cst (NULL_TREE, eh_index), NULL,
-                        create_artificial_label ());
+      last_case = build3 (CASE_LABEL_EXPR, void_type_node,
+                         build_int_cst (NULL_TREE, eh_index), NULL,
+                         create_artificial_label ());
       TREE_VEC_ELT (case_label_vec, last_case_index) = last_case;
       last_case_index++;
 
-      x = build (LABEL_EXPR, void_type_node, CASE_LABEL (last_case));
+      x = build1 (LABEL_EXPR, void_type_node, CASE_LABEL (last_case));
       append_to_statement_list (x, &switch_body);
       x = build_resx (get_eh_region_number (tf->region));
       append_to_statement_list (x, &switch_body);
@@ -1237,15 +1229,17 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
 
       if (q->index < 0)
        {
-         mod = build (MODIFY_EXPR, void_type_node, finally_tmp,
-                      build_int_cst (NULL_TREE, return_index));
+         mod = build_gimple_modify_stmt (finally_tmp,
+                                         build_int_cst (integer_type_node,
+                                                        return_index));
          do_return_redirection (q, finally_label, mod, &return_val);
          switch_id = return_index;
        }
       else
        {
-         mod = build (MODIFY_EXPR, void_type_node, finally_tmp,
-                      build_int_cst (NULL_TREE, q->index));
+         mod = build_gimple_modify_stmt (finally_tmp,
+                                         build_int_cst (integer_type_node,
+                                                        q->index));
          do_goto_redirection (q, finally_label, mod);
          switch_id = q->index;
        }
@@ -1253,15 +1247,15 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
       case_index = j + q->index;
       if (!TREE_VEC_ELT (case_label_vec, case_index))
        TREE_VEC_ELT (case_label_vec, case_index)
-         = build (CASE_LABEL_EXPR, void_type_node,
-                  build_int_cst (NULL_TREE, switch_id), NULL,
-                  /* We store the cont_stmt in the
-                     CASE_LABEL, so that we can recover it
-                     in the loop below.  We don't create
-                     the new label while walking the
-                     goto_queue because pointers don't
-                     offer a stable order.  */
-                  q->cont_stmt);
+         = build3 (CASE_LABEL_EXPR, void_type_node,
+                   build_int_cst (NULL_TREE, switch_id), NULL,
+                   /* We store the cont_stmt in the
+                      CASE_LABEL, so that we can recover it
+                      in the loop below.  We don't create
+                      the new label while walking the
+                      goto_queue because pointers don't
+                      offer a stable order.  */
+                   q->cont_stmt);
     }
   for (j = last_case_index; j < last_case_index + nlabels; j++)
     {
@@ -1277,7 +1271,7 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
       label = create_artificial_label ();
       CASE_LABEL (last_case) = label;
 
-      x = build (LABEL_EXPR, void_type_node, label);
+      x = build1 (LABEL_EXPR, void_type_node, label);
       append_to_statement_list (x, &switch_body);
       append_to_statement_list (cont_stmt, &switch_body);
       maybe_record_in_goto_queue (state, cont_stmt);
@@ -1318,7 +1312,7 @@ decide_copy_try_finally (int ndests, tree finally)
     return false;
 
   /* Finally estimate N times, plus N gotos.  */
-  f_estimate = estimate_num_insns (finally);
+  f_estimate = estimate_num_insns (finally, &eni_size_weights);
   f_estimate = (f_estimate + 1) * ndests;
 
   /* Switch statement (cost 10), N variable assignments, N gotos.  */
@@ -1503,6 +1497,10 @@ lower_eh_filter (struct leh_state *state, tree *tp)
                                         EH_FILTER_TYPES (inner));
   this_state = *state;
   this_state.cur_region = this_region;
+  /* For must not throw regions any cleanup regions inside it
+     can't reach outer catch regions.  */
+  if (EH_FILTER_MUST_NOT_THROW (inner))
+    this_state.prev_try = NULL;
 
   lower_eh_constructs_1 (&this_state, &TREE_OPERAND (*tp, 0));
 
@@ -1610,7 +1608,7 @@ lower_eh_constructs_1 (struct leh_state *state, tree *tp)
        }
       break;
 
-    case MODIFY_EXPR:
+    case GIMPLE_MODIFY_STMT:
       /* Look for things that can throw exceptions, and record them.  */
       if (state->cur_region && tree_could_throw_p (t))
        {
@@ -1669,7 +1667,7 @@ lower_eh_constructs_1 (struct leh_state *state, tree *tp)
     }
 }
 
-static void
+static unsigned int
 lower_eh_constructs (void)
 {
   struct leh_state null_state;
@@ -1685,6 +1683,7 @@ lower_eh_constructs (void)
   htab_delete (finally_tree);
 
   collect_eh_region_array ();
+  return 0;
 }
 
 struct tree_opt_pass pass_lower_eh =
@@ -1698,7 +1697,7 @@ struct tree_opt_pass pass_lower_eh =
   TV_TREE_EH,                          /* tv_id */
   PROP_gimple_lcf,                     /* properties_required */
   PROP_gimple_leh,                     /* properties_provided */
-  PROP_gimple_lcf,                     /* properties_destroyed */
+  0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   TODO_dump_func,                      /* todo_flags_finish */
   0                                    /* letter */
@@ -1713,7 +1712,7 @@ make_eh_edge (struct eh_region *region, void *data)
   tree stmt, lab;
   basic_block src, dst;
 
-  stmt = data;
+  stmt = (tree) data;
   lab = get_eh_region_tree_label (region);
 
   src = bb_for_stmt (stmt);
@@ -1755,7 +1754,7 @@ mark_eh_edge (struct eh_region *region, void *data)
   basic_block src, dst;
   edge e;
 
-  stmt = data;
+  stmt = (tree) data;
   lab = get_eh_region_tree_label (region);
 
   src = bb_for_stmt (stmt);
@@ -1764,18 +1763,18 @@ mark_eh_edge (struct eh_region *region, void *data)
   e = find_edge (src, dst);
   if (!e)
     {
-      error ("EH edge %i->%i is missing %i %i.", src->index, dst->index, src, dst);
+      error ("EH edge %i->%i is missing", src->index, dst->index);
       mark_eh_edge_found_error = true;
     }
   else if (!(e->flags & EDGE_EH))
     {
-      error ("EH edge %i->%i miss EH flag.", src->index, dst->index);
+      error ("EH edge %i->%i miss EH flag", src->index, dst->index);
       mark_eh_edge_found_error = true;
     }
   else if (e->aux)
     {
       /* ??? might not be mistake.  */
-      error ("EH edge %i->%i has duplicated regions.", src->index, dst->index);
+      error ("EH edge %i->%i has duplicated regions", src->index, dst->index);
       mark_eh_edge_found_error = true;
     }
   else
@@ -1827,7 +1826,7 @@ verify_eh_edges (tree stmt)
     {
       if ((e->flags & EDGE_EH) && !e->aux)
        {
-         error ("Unnecessary EH edge %i->%i", bb->index, e->dest->index);
+         error ("unnecessary EH edge %i->%i", bb->index, e->dest->index);
          mark_eh_edge_found_error = true;
          return true;
        }
@@ -1862,7 +1861,7 @@ tree_could_trap_p (tree expr)
          honor_nans = flag_trapping_math && !flag_finite_math_only;
          honor_snans = flag_signaling_nans != 0;
        }
-      else if (INTEGRAL_TYPE_P (t) && TYPE_TRAP_SIGNED (t))
+      else if (INTEGRAL_TYPE_P (t) && TYPE_OVERFLOW_TRAPS (t))
        honor_trapv = true;
     }
 
@@ -1880,19 +1879,21 @@ tree_could_trap_p (tree expr)
     case REALPART_EXPR:
     case IMAGPART_EXPR:
     case BIT_FIELD_REF:
+    case VIEW_CONVERT_EXPR:
     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
-        the access similarly to the case below.  */
-      if (!TREE_THIS_NOTRAP (expr))
+      base = TREE_OPERAND (expr, 0);
+      if (tree_could_trap_p (base))
        return true;
 
-      base = TREE_OPERAND (expr, 0);
-      return tree_could_trap_p (base);
+      if (TREE_THIS_NOTRAP (expr))
+       return false;
+
+      return !range_in_array_bounds_p (expr);
 
     case ARRAY_REF:
       base = TREE_OPERAND (expr, 0);
@@ -1952,9 +1953,6 @@ tree_could_trap_p (tree expr)
 
     case CONVERT_EXPR:
     case FIX_TRUNC_EXPR:
-    case FIX_CEIL_EXPR:
-    case FIX_FLOOR_EXPR:
-    case FIX_ROUND_EXPR:
       /* Conversion of floating point might trap.  */
       return honor_nans;
 
@@ -1996,12 +1994,12 @@ tree_could_throw_p (tree t)
 {
   if (!flag_exceptions)
     return false;
-  if (TREE_CODE (t) == MODIFY_EXPR)
+  if (TREE_CODE (t) == GIMPLE_MODIFY_STMT)
     {
       if (flag_non_call_exceptions
-         && tree_could_trap_p (TREE_OPERAND (t, 0)))
+         && tree_could_trap_p (GIMPLE_STMT_OPERAND (t, 0)))
        return true;
-      t = TREE_OPERAND (t, 1);
+      t = GIMPLE_STMT_OPERAND (t, 1);
     }
 
   if (TREE_CODE (t) == WITH_SIZE_EXPR)