OSDN Git Service

2006-02-08 Paolo Bonzini <bonzini@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / gimple-low.c
index 6e60aeb..69f9894 100644 (file)
@@ -16,8 +16,8 @@ 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.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -25,7 +25,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tm.h"
 #include "tree.h"
 #include "rtl.h"
-#include "errors.h"
 #include "varray.h"
 #include "tree-gimple.h"
 #include "tree-inline.h"
@@ -56,7 +55,6 @@ static void lower_stmt (tree_stmt_iterator *, struct lower_data *);
 static void lower_bind_expr (tree_stmt_iterator *, struct lower_data *);
 static void lower_cond_expr (tree_stmt_iterator *, struct lower_data *);
 static void lower_return_expr (tree_stmt_iterator *, struct lower_data *);
-static bool expand_var_p (tree);
 
 /* Lowers the body of current_function_decl.  */
 
@@ -71,13 +69,12 @@ lower_function_body (void)
 
   gcc_assert (TREE_CODE (bind) == BIND_EXPR);
 
+  memset (&data, 0, sizeof (data));
   data.block = DECL_INITIAL (current_function_decl);
   BLOCK_SUBBLOCKS (data.block) = NULL_TREE;
   BLOCK_CHAIN (data.block) = NULL_TREE;
   TREE_ASM_WRITTEN (data.block) = 1;
 
-  data.return_statements = NULL_TREE;
-
   *body_p = alloc_stmt_list ();
   i = tsi_start (*body_p);
   tsi_link_after (&i, bind, TSI_NEW_STMT);
@@ -92,7 +89,7 @@ lower_function_body (void)
       && (data.return_statements == NULL
           || TREE_OPERAND (TREE_VALUE (data.return_statements), 0) != NULL))
     {
-      x = build (RETURN_EXPR, void_type_node, NULL);
+      x = build1 (RETURN_EXPR, void_type_node, NULL);
       SET_EXPR_LOCATION (x, cfun->function_end_locus);
       tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
     }
@@ -101,7 +98,7 @@ lower_function_body (void)
      at the end of the function.  */
   for (t = data.return_statements ; t ; t = TREE_CHAIN (t))
     {
-      x = build (LABEL_EXPR, void_type_node, TREE_PURPOSE (t));
+      x = build1 (LABEL_EXPR, void_type_node, TREE_PURPOSE (t));
       tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
 
       /* Remove the line number from the representative return statement.
@@ -134,7 +131,7 @@ struct tree_opt_pass pass_lower_cf =
   0,                                   /* tv_id */
   PROP_gimple_any,                     /* properties_required */
   PROP_gimple_lcf,                     /* properties_provided */
-  PROP_gimple_any,                     /* properties_destroyed */
+  0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   TODO_dump_func,                      /* todo_flags_finish */
   0                                    /* letter */
@@ -145,7 +142,7 @@ struct tree_opt_pass pass_lower_cf =
    when they are changed -- if this has to be done, the lowering routine must
    do it explicitly.  DATA is passed through the recursion.  */
 
-void
+static void
 lower_stmt_body (tree expr, struct lower_data *data)
 {
   tree_stmt_iterator tsi;
@@ -154,6 +151,29 @@ lower_stmt_body (tree expr, struct lower_data *data)
     lower_stmt (&tsi, data);
 }
 
+
+/* Lower the OpenMP directive statement pointed by TSI.  DATA is
+   passed through the recursion.  */
+
+static void
+lower_omp_directive (tree_stmt_iterator *tsi, struct lower_data *data)
+{
+  tree clause, stmt;
+  
+  stmt = tsi_stmt (*tsi);
+
+  clause = (TREE_CODE (stmt) >= OMP_PARALLEL && TREE_CODE (stmt) <= OMP_SINGLE)
+          ? OMP_CLAUSES (stmt)
+          : NULL_TREE;
+
+  lower_stmt_body (OMP_BODY (stmt), data);
+  tsi_link_before (tsi, stmt, TSI_SAME_STMT);
+  tsi_link_before (tsi, OMP_BODY (stmt), TSI_SAME_STMT);
+  OMP_BODY (stmt) = NULL_TREE;
+  tsi_delink (tsi);
+}
+
+
 /* Lowers statement TSI.  DATA is passed through the recursion.  */
 
 static void
@@ -195,14 +215,21 @@ lower_stmt (tree_stmt_iterator *tsi, struct lower_data *data)
     case GOTO_EXPR:
     case LABEL_EXPR:
     case SWITCH_EXPR:
+    case OMP_RETURN_EXPR:
       break;
 
+    case OMP_PARALLEL:
+    case OMP_FOR:
+    case OMP_SECTIONS:
+    case OMP_SECTION:
+    case OMP_SINGLE:
+    case OMP_MASTER:
+    case OMP_ORDERED:
+    case OMP_CRITICAL:
+      lower_omp_directive (tsi, data);
+      return;
+
     default:
-#ifdef ENABLE_CHECKING
-      print_node_brief (stderr, "", stmt, 0);
-      internal_error ("unexpected node");
-#endif
-    case COMPOUND_EXPR:
       gcc_unreachable ();
     }
 
@@ -291,15 +318,16 @@ try_catch_may_fallthru (tree stmt)
       return false;
 
     case EH_FILTER_EXPR:
-      /* If the exception does not match EH_FILTER_TYPES, we will
-        execute EH_FILTER_FAILURE, and we will fall through if that
-        falls through.  If the exception does match EH_FILTER_TYPES,
-        we will fall through.  We don't know which exceptions may be
-        generated, so we just check for EH_FILTER_TYPES being NULL,
-        in which case we know that that the exception does not
-        match.  */
-      return (EH_FILTER_TYPES (tsi_stmt (i)) != NULL
-             || block_may_fallthru (EH_FILTER_FAILURE (tsi_stmt (i))));
+      /* The exception filter expression only matters if there is an
+        exception.  If the exception does not match EH_FILTER_TYPES,
+        we will execute EH_FILTER_FAILURE, and we will fall through
+        if that falls through.  If the exception does match
+        EH_FILTER_TYPES, the stack unwinder will continue up the
+        stack, so we will not fall through.  We don't know whether we
+        will throw an exception which matches EH_FILTER_TYPES or not,
+        so we just ignore EH_FILTER_TYPES and assume that we might
+        throw an exception which doesn't match.  */
+      return block_may_fallthru (EH_FILTER_FAILURE (tsi_stmt (i)));
 
     default:
       /* This case represents statements to be executed when an
@@ -368,6 +396,9 @@ block_may_fallthru (tree block)
     case CALL_EXPR:
       /* Functions that do not return do not fall through.  */
       return (call_expr_flags (stmt) & ECF_NORETURN) == 0;
+    
+    case CLEANUP_POINT_EXPR:
+      return block_may_fallthru (TREE_OPERAND (stmt, 0));
 
     default:
       return true;
@@ -500,110 +531,54 @@ lower_return_expr (tree_stmt_iterator *tsi, struct lower_data *data)
 
   /* Generate a goto statement and remove the return statement.  */
  found:
-  t = build (GOTO_EXPR, void_type_node, label);
+  t = build1 (GOTO_EXPR, void_type_node, label);
   SET_EXPR_LOCUS (t, EXPR_LOCUS (stmt));
   tsi_link_before (tsi, t, TSI_SAME_STMT);
   tsi_delink (tsi);
 }
 \f
 
-/* Record the variables in VARS.  */
+/* Record the variables in VARS into function FN.  */
 
 void
-record_vars (tree vars)
+record_vars_into (tree vars, tree fn)
 {
+  struct function *saved_cfun = cfun;
+
+  if (fn != current_function_decl)
+    cfun = DECL_STRUCT_FUNCTION (fn);
+
   for (; vars; vars = TREE_CHAIN (vars))
     {
       tree var = vars;
 
+      /* BIND_EXPRs contains also function/type/constant declarations
+         we don't need to care about.  */
+      if (TREE_CODE (var) != VAR_DECL)
+       continue;
+
       /* Nothing to do in this case.  */
       if (DECL_EXTERNAL (var))
        continue;
-      if (TREE_CODE (var) == FUNCTION_DECL)
-       continue;
 
       /* Record the variable.  */
       cfun->unexpanded_var_list = tree_cons (NULL_TREE, var,
                                             cfun->unexpanded_var_list);
     }
-}
-
-/* Check whether to expand a variable VAR.  */
-
-static bool
-expand_var_p (tree var)
-{
-  struct var_ann_d *ann;
-
-  if (TREE_CODE (var) != VAR_DECL)
-    return true;
-
-  /* Leave statics and externals alone.  */
-  if (TREE_STATIC (var) || DECL_EXTERNAL (var))
-    return true;
 
-  /* Remove all unused local variables.  */
-  ann = var_ann (var);
-  if (!ann || !ann->used)
-    return false;
-
-  return true;
+  if (fn != current_function_decl)
+    cfun = saved_cfun;
 }
 
-/* Throw away variables that are unused.  */
-
-static void
-remove_useless_vars (void)
-{
-  tree var, *cell;
-  FILE *df = NULL;
-
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    {
-      df = dump_file;
-      fputs ("Discarding as unused:\n", df);
-    }
-
-  for (cell = &cfun->unexpanded_var_list; *cell; )
-    {
-      var = TREE_VALUE (*cell);
-
-      if (!expand_var_p (var))
-       {
-         if (df)
-           {
-             fputs ("  ", df);
-             print_generic_expr (df, var, dump_flags);
-             fputc ('\n', df);
-           }
-
-         *cell = TREE_CHAIN (*cell);
-         continue;
-       }
 
-      cell = &TREE_CHAIN (*cell);
-    }
+/* Record the variables in VARS into current_function_decl.  */
 
-  if (df)
-    fputc ('\n', df);
+void
+record_vars (tree vars)
+{
+  record_vars_into (vars, current_function_decl);
 }
 
-struct tree_opt_pass pass_remove_useless_vars = 
-{
-  "vars",                              /* name */
-  NULL,                                        /* gate */
-  remove_useless_vars,                 /* execute */
-  NULL,                                        /* sub */
-  NULL,                                        /* next */
-  0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
-  0,                                   /* properties_required */
-  0,                                   /* properties_provided */
-  0,                                   /* properties_destroyed */
-  0,                                   /* todo_flags_start */
-  TODO_dump_func,                      /* todo_flags_finish */
-  0                                    /* letter */
-};
 
 /* Mark BLOCK used if it has a used variable in it, then recurse over its
    subblocks.  */