OSDN Git Service

2008-08-09 Paul Thomas <pault@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / stmt.c
index 11cae96..38d7b43 100644 (file)
@@ -1,13 +1,13 @@
 /* Expands front end tree to back end RTL for GCC
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the 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, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* This file handles the generation of rtl code from tree structure
    above the level of expressions, using subroutines in exp*.c and emit-rtl.c.
@@ -50,6 +49,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "optabs.h"
 #include "target.h"
 #include "regs.h"
+#include "alloc-pool.h"
 \f
 /* Functions and data structures for expanding case statements.  */
 
@@ -80,7 +80,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    For very small, suitable switch statements, we can generate a series
    of simple bit test and branches instead.  */
 
-struct case_node GTY(())
+struct case_node
 {
   struct case_node     *left;  /* Left son in binary tree */
   struct case_node     *right; /* Right son in binary tree; also node chain */
@@ -122,7 +122,7 @@ static int node_has_high_bound (case_node_ptr, tree);
 static int node_is_bounded (case_node_ptr, tree);
 static void emit_case_nodes (rtx, case_node_ptr, rtx, tree);
 static struct case_node *add_case_node (struct case_node *, tree,
-                                       tree, tree, tree);
+                                        tree, tree, tree, alloc_pool);
 
 \f
 /* Return the rtx-label that corresponds to a LABEL_DECL,
@@ -160,8 +160,7 @@ force_label_rtx (tree label)
   else
     p = cfun;
 
-  p->expr->x_forced_labels = gen_rtx_EXPR_LIST (VOIDmode, ref,
-                                               p->expr->x_forced_labels);
+  forced_labels = gen_rtx_EXPR_LIST (VOIDmode, ref, forced_labels);
   return ref;
 }
 
@@ -334,7 +333,7 @@ parse_output_constraint (const char **constraint_p, int operand_num,
                 *p, operand_num);
 
       /* Make a copy of the constraint.  */
-      buf = alloca (c_len + 1);
+      buf = XALLOCAVEC (char, c_len + 1);
       strcpy (buf, constraint);
       /* Swap the first character and the `=' or `+'.  */
       buf[p - constraint] = buf[0];
@@ -364,7 +363,7 @@ parse_output_constraint (const char **constraint_p, int operand_num,
          }
        break;
 
-      case 'V':  case 'm':  case 'o':
+      case 'V':  case TARGET_MEM_CONSTRAINT:  case 'o':
        *allows_mem = true;
        break;
 
@@ -463,7 +462,7 @@ parse_input_constraint (const char **constraint_p, int input_num,
          }
        break;
 
-      case 'V':  case 'm':  case 'o':
+      case 'V':  case TARGET_MEM_CONSTRAINT:  case 'o':
        *allows_mem = true;
        break;
 
@@ -566,7 +565,7 @@ decl_overlaps_hard_reg_set_p (tree *declp, int *walk_subtrees ATTRIBUTE_UNUSED,
                              void *data)
 {
   tree decl = *declp;
-  const HARD_REG_SET *regs = data;
+  const HARD_REG_SET *const regs = (const HARD_REG_SET *) data;
 
   if (TREE_CODE (decl) == VAR_DECL)
     {
@@ -623,7 +622,7 @@ tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
    STRING is the instruction template.
    OUTPUTS is a list of output arguments (lvalues); INPUTS a list of inputs.
    Each output or input has an expression in the TREE_VALUE and
-   and a tree list in TREE_PURPOSE which in turn contains a constraint
+   a tree list in TREE_PURPOSE which in turn contains a constraint
    name in TREE_VALUE (or NULL_TREE) and a constraint string
    in TREE_PURPOSE.
    CLOBBERS is a list of STRING_CST nodes each naming a hard register
@@ -652,13 +651,11 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
   tree t;
   int i;
   /* Vector of RTX's of evaluated output operands.  */
-  rtx *output_rtx = alloca (noutputs * sizeof (rtx));
-  int *inout_opnum = alloca (noutputs * sizeof (int));
-  rtx *real_output_rtx = alloca (noutputs * sizeof (rtx));
-  enum machine_mode *inout_mode
-    = alloca (noutputs * sizeof (enum machine_mode));
-  const char **constraints
-    = alloca ((noutputs + ninputs) * sizeof (const char *));
+  rtx *output_rtx = XALLOCAVEC (rtx, noutputs);
+  int *inout_opnum = XALLOCAVEC (int, noutputs);
+  rtx *real_output_rtx = XALLOCAVEC (rtx, noutputs);
+  enum machine_mode *inout_mode = XALLOCAVEC (enum machine_mode, noutputs);
+  const char **constraints = XALLOCAVEC (const char *, noutputs + ninputs);
   int old_generating_concat_p = generating_concat_p;
 
   /* An ASM with no outputs needs to be treated as volatile, for now.  */
@@ -1078,6 +1075,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
     if (real_output_rtx[i])
       emit_move_insn (real_output_rtx[i], output_rtx[i]);
 
+  crtl->has_asm_statement = 1;
   free_temp_slots ();
 }
 
@@ -1358,9 +1356,6 @@ expand_expr_stmt (tree exp)
   tree type;
 
   value = expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
-  if (GIMPLE_TUPLE_P (exp))
-    type = void_type_node;
-  else
   type = TREE_TYPE (exp);
 
   /* If all we do is reference a volatile value in memory,
@@ -1392,7 +1387,7 @@ expand_expr_stmt (tree exp)
    (potential) location of the expression.  */
 
 int
-warn_if_unused_value (tree exp, location_t locus)
+warn_if_unused_value (const_tree exp, location_t locus)
 {
  restart:
   if (TREE_USED (exp) || TREE_NO_WARNING (exp))
@@ -1414,7 +1409,6 @@ warn_if_unused_value (tree exp, location_t locus)
     case PREDECREMENT_EXPR:
     case POSTDECREMENT_EXPR:
     case MODIFY_EXPR:
-    case GIMPLE_MODIFY_STMT:
     case INIT_EXPR:
     case TARGET_EXPR:
     case CALL_EXPR:
@@ -1478,7 +1472,7 @@ warn_if_unused_value (tree exp, location_t locus)
        return 0;
 
     warn:
-      warning (0, "%Hvalue computed is not used", &locus);
+      warning (OPT_Wunused_value, "%Hvalue computed is not used", &locus);
       return 1;
     }
 }
@@ -1583,10 +1577,10 @@ expand_return (tree retval)
       expand_null_return ();
       return;
     }
-  else if ((TREE_CODE (retval) == GIMPLE_MODIFY_STMT
+  else if ((TREE_CODE (retval) == MODIFY_EXPR
            || TREE_CODE (retval) == INIT_EXPR)
-          && TREE_CODE (GENERIC_TREE_OPERAND (retval, 0)) == RESULT_DECL)
-    retval_rhs = GENERIC_TREE_OPERAND (retval, 1);
+          && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
+    retval_rhs = TREE_OPERAND (retval, 1);
   else
     retval_rhs = retval;
 
@@ -1605,7 +1599,7 @@ expand_return (tree retval)
      (and in expand_call).  */
 
   else if (retval_rhs != 0
-          && TYPE_MODE (GENERIC_TREE_TYPE (retval_rhs)) == BLKmode
+          && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
           && REG_P (result_rtl))
     {
       int i;
@@ -1616,7 +1610,7 @@ expand_return (tree retval)
       int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
       unsigned int bitsize
        = MIN (TYPE_ALIGN (TREE_TYPE (retval_rhs)), BITS_PER_WORD);
-      rtx *result_pseudos = alloca (sizeof (rtx) * n_regs);
+      rtx *result_pseudos = XALLOCAVEC (rtx, n_regs);
       rtx result_reg, src = NULL_RTX, dst = NULL_RTX;
       rtx result_val = expand_normal (retval_rhs);
       enum machine_mode tmpmode, result_reg_mode;
@@ -1747,7 +1741,7 @@ expand_return (tree retval)
    *that* node in turn will point to the relevant FUNCTION_DECL node.  */
 
 int
-is_body_block (tree stmt)
+is_body_block (const_tree stmt)
 {
   if (lang_hooks.no_body_blocks)
     return 0;
@@ -1775,11 +1769,11 @@ expand_nl_goto_receiver (void)
 {
   /* Clobber the FP when we get here, so we have to make sure it's
      marked as used by this function.  */
-  emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
+  emit_use (hard_frame_pointer_rtx);
 
   /* Mark the static chain as clobbered here so life information
      doesn't get messed up for it.  */
-  emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
+  emit_clobber (static_chain_rtx);
 
 #ifdef HAVE_nonlocal_goto
   if (! HAVE_nonlocal_goto)
@@ -1819,8 +1813,8 @@ expand_nl_goto_receiver (void)
        {
          /* Now restore our arg pointer from the address at which it
             was saved in our stack frame.  */
-         emit_move_insn (virtual_incoming_args_rtx,
-                         copy_to_reg (get_arg_pointer_save_area (cfun)));
+         emit_move_insn (crtl->args.internal_arg_pointer,
+                         copy_to_reg (get_arg_pointer_save_area ()));
        }
     }
 #endif
@@ -1898,19 +1892,11 @@ expand_decl (tree decl)
 
       /* Note if the object is a user variable.  */
       if (!DECL_ARTIFICIAL (decl))
-       {
          mark_user_reg (DECL_RTL (decl));
 
-         /* Trust user variables which have a pointer type to really
-            be pointers.  Do not trust compiler generated temporaries
-            as our type system is totally busted as it relates to
-            pointer arithmetic which translates into lots of compiler
-            generated objects with pointer types, but which are not really
-            pointers.  */
-         if (POINTER_TYPE_P (type))
-           mark_reg_pointer (DECL_RTL (decl),
-                             TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
-       }
+      if (POINTER_TYPE_P (type))
+       mark_reg_pointer (DECL_RTL (decl),
+                         TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
     }
 
   else if (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST
@@ -2002,8 +1988,9 @@ expand_stack_save (void)
 void
 expand_stack_restore (tree var)
 {
-  rtx sa = DECL_RTL (var);
+  rtx sa = expand_normal (var);
 
+  sa = convert_memory_address (Pmode, sa);
   emit_stack_restore (SAVE_BLOCK, sa, NULL_RTX);
 }
 \f
@@ -2075,7 +2062,7 @@ expand_anon_union_decl (tree decl, tree cleanup ATTRIBUTE_UNUSED,
 
 static struct case_node *
 add_case_node (struct case_node *head, tree type, tree low, tree high,
-              tree label)
+               tree label, alloc_pool case_node_pool)
 {
   tree min_value, max_value;
   struct case_node *r;
@@ -2127,7 +2114,7 @@ add_case_node (struct case_node *head, tree type, tree low, tree high,
 
 
   /* Add this label to the chain.  Make sure to drop overflow flags.  */
-  r = ggc_alloc (sizeof (struct case_node));
+  r = (struct case_node *) pool_alloc (case_node_pool);
   r->low = build_int_cst_wide (TREE_TYPE (low), TREE_INT_CST_LOW (low),
                               TREE_INT_CST_HIGH (low));
   r->high = build_int_cst_wide (TREE_TYPE (high), TREE_INT_CST_LOW (high),
@@ -2143,7 +2130,7 @@ add_case_node (struct case_node *head, tree type, tree low, tree high,
 
 /* By default, enable case bit tests on targets with ashlsi3.  */
 #ifndef CASE_USE_BIT_TESTS
-#define CASE_USE_BIT_TESTS  (ashl_optab->handlers[word_mode].insn_code \
+#define CASE_USE_BIT_TESTS  (optab_handler (ashl_optab, word_mode)->insn_code \
                             != CODE_FOR_nothing)
 #endif
 
@@ -2189,8 +2176,8 @@ bool lshift_cheap_p (void)
 static int
 case_bit_test_cmp (const void *p1, const void *p2)
 {
-  const struct case_bit_test *d1 = p1;
-  const struct case_bit_test *d2 = p2;
+  const struct case_bit_test *const d1 = (const struct case_bit_test *) p1;
+  const struct case_bit_test *const d2 = (const struct case_bit_test *) p2;
 
   if (d2->bits != d1->bits)
     return d2->bits - d1->bits;
@@ -2266,8 +2253,9 @@ emit_case_bit_tests (tree index_type, tree index_expr, tree minval,
 
   mode = TYPE_MODE (index_type);
   expr = expand_normal (range);
-  emit_cmp_and_jump_insns (index, expr, GTU, NULL_RTX, mode, 1,
-                          default_label);
+  if (default_label)
+    emit_cmp_and_jump_insns (index, expr, GTU, NULL_RTX, mode, 1,
+                            default_label);
 
   index = convert_to_mode (word_mode, index, 0);
   index = expand_binop (word_mode, ashl_optab, const1_rtx,
@@ -2282,7 +2270,8 @@ emit_case_bit_tests (tree index_type, tree index_expr, tree minval,
                               word_mode, 1, test[i].label);
     }
 
-  emit_jump (default_label);
+  if (default_label)
+    emit_jump (default_label);
 }
 
 #ifndef HAVE_casesi
@@ -2328,7 +2317,11 @@ expand_case (tree exp)
   struct case_node *case_list = 0;
 
   /* Label to jump to if no case matches.  */
-  tree default_label_decl;
+  tree default_label_decl = NULL_TREE;
+
+  alloc_pool case_node_pool = create_alloc_pool ("struct case_node pool",
+                                                 sizeof (struct case_node),
+                                                 100);
 
   /* The switch body is lowered in gimplify.c, we should never have
      switches with a non-NULL SWITCH_BODY here.  */
@@ -2342,18 +2335,21 @@ expand_case (tree exp)
     {
       tree elt;
       bitmap label_bitmap;
+      int vl = TREE_VEC_LENGTH (vec);
 
       /* cleanup_tree_cfg removes all SWITCH_EXPR with their index
         expressions being INTEGER_CST.  */
       gcc_assert (TREE_CODE (index_expr) != INTEGER_CST);
 
-      /* The default case is at the end of TREE_VEC.  */
-      elt = TREE_VEC_ELT (vec, TREE_VEC_LENGTH (vec) - 1);
-      gcc_assert (!CASE_HIGH (elt));
-      gcc_assert (!CASE_LOW (elt));
-      default_label_decl = CASE_LABEL (elt);
+      /* The default case, if ever taken, is at the end of TREE_VEC.  */
+      elt = TREE_VEC_ELT (vec, vl - 1);
+      if (!CASE_LOW (elt) && !CASE_HIGH (elt))
+       {
+         default_label_decl = CASE_LABEL (elt);
+         --vl;
+       }
 
-      for (i = TREE_VEC_LENGTH (vec) - 1; --i >= 0; )
+      for (i = vl - 1; i >= 0; --i)
        {
          tree low, high;
          elt = TREE_VEC_ELT (vec, i);
@@ -2363,16 +2359,17 @@ expand_case (tree exp)
          high = CASE_HIGH (elt);
 
          /* Discard empty ranges.  */
-         if (high && INT_CST_LT (high, low))
+         if (high && tree_int_cst_lt (high, low))
            continue;
 
          case_list = add_case_node (case_list, index_type, low, high,
-                                    CASE_LABEL (elt));
+                                     CASE_LABEL (elt), case_node_pool);
        }
 
 
       before_case = start = get_last_insn ();
-      default_label = label_rtx (default_label_decl);
+      if (default_label_decl)
+       default_label = label_rtx (default_label_decl);
 
       /* Get upper and lower bounds of case values.  */
 
@@ -2390,9 +2387,9 @@ expand_case (tree exp)
            }
          else
            {
-             if (INT_CST_LT (n->low, minval))
+             if (tree_int_cst_lt (n->low, minval))
                minval = n->low;
-             if (INT_CST_LT (maxval, n->high))
+             if (tree_int_cst_lt (maxval, n->high))
                maxval = n->high;
            }
          /* A range counts double, since it requires two compares.  */
@@ -2417,7 +2414,9 @@ expand_case (tree exp)
         type, so we may still get a zero here.  */
       if (count == 0)
        {
-         emit_jump (default_label);
+         if (default_label)
+           emit_jump (default_label);
+          free_alloc_pool (case_node_pool);
          return;
        }
 
@@ -2512,13 +2511,15 @@ expand_case (tree exp)
               && estimate_case_costs (case_list));
          balance_case_nodes (&case_list, NULL);
          emit_case_nodes (index, case_list, default_label, index_type);
-         emit_jump (default_label);
+         if (default_label)
+           emit_jump (default_label);
        }
       else
        {
+         rtx fallback_label = label_rtx (case_list->code_label);
          table_label = gen_label_rtx ();
          if (! try_casesi (index_type, index_expr, minval, range,
-                           table_label, default_label))
+                           table_label, default_label, fallback_label))
            {
              bool ok;
 
@@ -2540,7 +2541,7 @@ expand_case (tree exp)
          /* Get table of labels to jump to, in order of case index.  */
 
          ncases = tree_low_cst (range, 0) + 1;
-         labelvec = alloca (ncases * sizeof (rtx));
+         labelvec = XALLOCAVEC (rtx, ncases);
          memset (labelvec, 0, ncases * sizeof (rtx));
 
          for (n = case_list; n; n = n->right)
@@ -2561,7 +2562,12 @@ expand_case (tree exp)
                  = gen_rtx_LABEL_REF (Pmode, label_rtx (n->code_label));
            }
 
-         /* Fill in the gaps with the default.  */
+         /* Fill in the gaps with the default.  We may have gaps at
+            the beginning if we tried to avoid the minval subtraction,
+            so substitute some label even if the default label was
+            deemed unreachable.  */
+         if (!default_label)
+           default_label = fallback_label;
          for (i = 0; i < ncases; i++)
            if (labelvec[i] == 0)
              labelvec[i] = gen_rtx_LABEL_REF (Pmode, default_label);
@@ -2588,6 +2594,7 @@ expand_case (tree exp)
     }
 
   free_temp_slots ();
+  free_alloc_pool (case_node_pool);
 }
 
 /* Generate code to jump to LABEL if OP0 and OP1 are equal in mode MODE.  */
@@ -2665,7 +2672,8 @@ estimate_case_costs (case_node_ptr node)
 
   for (n = node; n; n = n->right)
     {
-      if ((INT_CST_LT (n->low, min_ascii)) || INT_CST_LT (max_ascii, n->high))
+      if (tree_int_cst_lt (n->low, min_ascii)
+         || tree_int_cst_lt (max_ascii, n->high))
        return 0;
 
       for (i = (HOST_WIDE_INT) TREE_INT_CST_LOW (n->low);
@@ -3044,7 +3052,8 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
              emit_case_nodes (index, node->left, default_label, index_type);
              /* If left-hand subtree does nothing,
                 go to default.  */
-             emit_jump (default_label);
+             if (default_label)
+               emit_jump (default_label);
 
              /* Code branches here for the right-hand subtree.  */
              expand_label (test_label);
@@ -3179,7 +3188,8 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
            {
              /* If the left-hand subtree fell through,
                 don't let it fall into the right-hand subtree.  */
-             emit_jump (default_label);
+             if (default_label)
+               emit_jump (default_label);
 
              expand_label (test_label);
              emit_case_nodes (index, node->right, default_label, index_type);