OSDN Git Service

2009-08-17 Emmanuel Briot <briot@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / stmt.c
index f05cd09..fe60ba6 100644 (file)
@@ -1,6 +1,6 @@
 /* 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, 2008
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "target.h"
 #include "regs.h"
 #include "alloc-pool.h"
+#include "pretty-print.h"
 \f
 /* Functions and data structures for expanding case statements.  */
 
@@ -151,15 +152,9 @@ force_label_rtx (tree label)
 {
   rtx ref = label_rtx (label);
   tree function = decl_function_context (label);
-  struct function *p;
 
   gcc_assert (function);
 
-  if (function != current_function_decl)
-    p = find_function_data (function);
-  else
-    p = cfun;
-
   forced_labels = gen_rtx_EXPR_LIST (VOIDmode, ref, forced_labels);
   return ref;
 }
@@ -606,8 +601,8 @@ tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
 
   if (overlap)
     {
-      error ("asm-specifier for variable %qs conflicts with asm clobber list",
-            IDENTIFIER_POINTER (DECL_NAME (overlap)));
+      error ("asm-specifier for variable %qE conflicts with asm clobber list",
+            DECL_NAME (overlap));
 
       /* Reset registerness to stop multiple errors emitted for a single
         variable.  */
@@ -892,7 +887,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
       else if (MEM_P (op))
        op = validize_mem (op);
 
-      if (asm_operand_ok (op, constraint) <= 0)
+      if (asm_operand_ok (op, constraint, NULL) <= 0)
        {
          if (allows_reg && TYPE_MODE (type) != BLKmode)
            op = force_reg (TYPE_MODE (type), op);
@@ -1328,7 +1323,7 @@ resolve_operand_name_1 (char *p, tree outputs, tree inputs)
     }
 
   *q = '\0';
-  error ("undefined named operand %qs", p + 1);
+  error ("undefined named operand %qs", identifier_to_locale (p + 1));
   op = 0;
  found:
 
@@ -1424,6 +1419,7 @@ warn_if_unused_value (const_tree exp, location_t locus)
       goto restart;
 
     case SAVE_EXPR:
+    case NON_LVALUE_EXPR:
       exp = TREE_OPERAND (exp, 0);
       goto restart;
 
@@ -1472,7 +1468,7 @@ warn_if_unused_value (const_tree exp, location_t locus)
        return 0;
 
     warn:
-      warning (OPT_Wunused_value, "%Hvalue computed is not used", &locus);
+      warning_at (locus, OPT_Wunused_value, "value computed is not used");
       return 1;
     }
 }
@@ -1515,24 +1511,22 @@ expand_naked_return (void)
 static void
 expand_value_return (rtx val)
 {
-  /* Copy the value to the return location
-     unless it's already there.  */
+  /* Copy the value to the return location unless it's already there.  */
 
-  rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
+  tree decl = DECL_RESULT (current_function_decl);
+  rtx return_reg = DECL_RTL (decl);
   if (return_reg != val)
     {
-      tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
-      if (targetm.calls.promote_function_return (TREE_TYPE (current_function_decl)))
-      {
-       int unsignedp = TYPE_UNSIGNED (type);
-       enum machine_mode old_mode
-         = DECL_MODE (DECL_RESULT (current_function_decl));
-       enum machine_mode mode
-         = promote_mode (type, old_mode, &unsignedp, 1);
-
-       if (mode != old_mode)
-         val = convert_modes (mode, old_mode, val, unsignedp);
-      }
+      tree funtype = TREE_TYPE (current_function_decl);
+      tree type = TREE_TYPE (decl);
+      int unsignedp = TYPE_UNSIGNED (type);
+      enum machine_mode old_mode = DECL_MODE (decl);
+      enum machine_mode mode = promote_function_mode (type, old_mode,
+                                                     &unsignedp, funtype, 1);
+
+      if (mode != old_mode)
+       val = convert_modes (mode, old_mode, val, unsignedp);
+
       if (GET_CODE (return_reg) == PARALLEL)
        emit_group_load (return_reg, val, type, int_size_in_bytes (type));
       else
@@ -1730,38 +1724,6 @@ expand_return (tree retval)
     }
 }
 \f
-/* Given a pointer to a BLOCK node return nonzero if (and only if) the node
-   in question represents the outermost pair of curly braces (i.e. the "body
-   block") of a function or method.
-
-   For any BLOCK node representing a "body block" of a function or method, the
-   BLOCK_SUPERCONTEXT of the node will point to another BLOCK node which
-   represents the outermost (function) scope for the function or method (i.e.
-   the one which includes the formal parameters).  The BLOCK_SUPERCONTEXT of
-   *that* node in turn will point to the relevant FUNCTION_DECL node.  */
-
-int
-is_body_block (const_tree stmt)
-{
-  if (lang_hooks.no_body_blocks)
-    return 0;
-
-  if (TREE_CODE (stmt) == BLOCK)
-    {
-      tree parent = BLOCK_SUPERCONTEXT (stmt);
-
-      if (parent && TREE_CODE (parent) == BLOCK)
-       {
-         tree grandparent = BLOCK_SUPERCONTEXT (parent);
-
-         if (grandparent && TREE_CODE (grandparent) == FUNCTION_DECL)
-           return 1;
-       }
-    }
-
-  return 0;
-}
-
 /* Emit code to restore vital registers at the beginning of a nonlocal goto
    handler.  */
 static void
@@ -1884,9 +1846,7 @@ expand_decl (tree decl)
   else if (use_register_for_decl (decl))
     {
       /* Automatic variable that can go in a register.  */
-      int unsignedp = TYPE_UNSIGNED (type);
-      enum machine_mode reg_mode
-       = promote_mode (type, DECL_MODE (decl), &unsignedp, 0);
+      enum machine_mode reg_mode = promote_decl_mode (decl, NULL);
 
       SET_DECL_RTL (decl, gen_reg_rtx (reg_mode));
 
@@ -1958,66 +1918,6 @@ expand_stack_restore (tree var)
   emit_stack_restore (SAVE_BLOCK, sa, NULL_RTX);
 }
 \f
-/* DECL is an anonymous union.  CLEANUP is a cleanup for DECL.
-   DECL_ELTS is the list of elements that belong to DECL's type.
-   In each, the TREE_VALUE is a VAR_DECL, and the TREE_PURPOSE a cleanup.  */
-
-void
-expand_anon_union_decl (tree decl, tree cleanup ATTRIBUTE_UNUSED,
-                       tree decl_elts)
-{
-  rtx x;
-  tree t;
-
-  /* If any of the elements are addressable, so is the entire union.  */
-  for (t = decl_elts; t; t = TREE_CHAIN (t))
-    if (TREE_ADDRESSABLE (TREE_VALUE (t)))
-      {
-       TREE_ADDRESSABLE (decl) = 1;
-       break;
-      }
-
-  expand_decl (decl);
-  x = DECL_RTL (decl);
-
-  /* Go through the elements, assigning RTL to each.  */
-  for (t = decl_elts; t; t = TREE_CHAIN (t))
-    {
-      tree decl_elt = TREE_VALUE (t);
-      enum machine_mode mode = TYPE_MODE (TREE_TYPE (decl_elt));
-      rtx decl_rtl;
-
-      /* If any of the elements are addressable, so is the entire
-        union.  */
-      if (TREE_USED (decl_elt))
-       TREE_USED (decl) = 1;
-
-      /* Propagate the union's alignment to the elements.  */
-      DECL_ALIGN (decl_elt) = DECL_ALIGN (decl);
-      DECL_USER_ALIGN (decl_elt) = DECL_USER_ALIGN (decl);
-
-      /* If the element has BLKmode and the union doesn't, the union is
-         aligned such that the element doesn't need to have BLKmode, so
-         change the element's mode to the appropriate one for its size.  */
-      if (mode == BLKmode && DECL_MODE (decl) != BLKmode)
-       DECL_MODE (decl_elt) = mode
-         = mode_for_size_tree (DECL_SIZE (decl_elt), MODE_INT, 1);
-
-      if (mode == GET_MODE (x))
-       decl_rtl = x;
-      else if (MEM_P (x))
-        /* (SUBREG (MEM ...)) at RTL generation time is invalid, so we
-           instead create a new MEM rtx with the proper mode.  */
-       decl_rtl = adjust_address_nv (x, mode, 0);
-      else
-       {
-         gcc_assert (REG_P (x));
-         decl_rtl = gen_lowpart_SUBREG (mode, x);
-       }
-      SET_DECL_RTL (decl_elt, decl_rtl);
-    }
-}
-\f
 /* Do the insertion of a case label into case_list.  The labels are
    fed to us in descending order from the sorted vector of case labels used
    in the tree part of the middle end.  So the list we construct is
@@ -2125,7 +2025,8 @@ bool lshift_cheap_p (void)
   if (!init)
     {
       rtx reg = gen_rtx_REG (word_mode, 10000);
-      int cost = rtx_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg), SET);
+      int cost = rtx_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg), SET,
+                          optimize_insn_for_speed_p ());
       cheap = cost < COSTS_N_INSNS (3);
       init = true;
     }
@@ -2417,9 +2318,9 @@ expand_case (tree exp)
         If the switch-index is a constant, do it this way
         because we can optimize it.  */
 
-      else if (count < case_values_threshold ()
+      else if (count < targetm.case_values_threshold ()
               || compare_tree_int (range,
-                                   (optimize_size ? 3 : 10) * count) > 0
+                                   (optimize_insn_for_size_p () ? 3 : 10) * count) > 0
               /* RANGE may be signed, and really large ranges will show up
                  as negative numbers.  */
               || compare_tree_int (range, 0) < 0
@@ -2489,7 +2390,7 @@ expand_case (tree exp)
 
              /* Index jumptables from zero for suitable values of
                  minval to avoid a subtraction.  */
-             if (! optimize_size
+             if (optimize_insn_for_speed_p ()
                  && compare_tree_int (minval, 0) > 0
                  && compare_tree_int (minval, 3) < 0)
                {
@@ -3000,7 +2901,9 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
              /* Neither node is bounded.  First distinguish the two sides;
                 then emit the code for one side at a time.  */
 
-             tree test_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+             tree test_label
+               = build_decl (CURR_INSN_LOCATION,
+                             LABEL_DECL, NULL_TREE, NULL_TREE);
 
              /* See if the value is on the right.  */
              emit_cmp_and_jump_insns (index,
@@ -3123,7 +3026,8 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
              /* Right hand node requires testing.
                 Branch to a label where we will handle it later.  */
 
-             test_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+             test_label = build_decl (CURR_INSN_LOCATION,
+                                      LABEL_DECL, NULL_TREE, NULL_TREE);
              emit_cmp_and_jump_insns (index,
                                       convert_modes
                                       (mode, imode,