OSDN Git Service

2007-01-07 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / tree-nested.c
index 4c65a1d..fdf39cc 100644 (file)
@@ -1,5 +1,5 @@
 /* Nested function decomposition for trees.
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -104,6 +104,7 @@ struct nesting_info GTY ((chain_next ("%h.next")))
 
   bool any_parm_remapped;
   bool any_tramp_created;
+  char static_chain_added;
 };
 
 
@@ -147,6 +148,10 @@ create_tmp_var_for (struct nesting_info *info, tree type, const char *prefix)
   DECL_CONTEXT (tmp_var) = info->context;
   TREE_CHAIN (tmp_var) = info->new_local_var_chain;
   DECL_SEEN_IN_BIND_EXPR_P (tmp_var) = 1;
+  if (TREE_CODE (type) == COMPLEX_TYPE
+      || TREE_CODE (type) == VECTOR_TYPE)
+    DECL_GIMPLE_REG_P (tmp_var) = 1;
+
   info->new_local_var_chain = tmp_var;
 
   return tmp_var;
@@ -178,7 +183,7 @@ build_addr (tree exp, tree context)
   save_context = current_function_decl;
   current_function_decl = context;
   retval = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
-  current_function_decl = save_context;;
+  current_function_decl = save_context;
   return retval;
 }
 
@@ -384,7 +389,7 @@ init_tmp_var (struct nesting_info *info, tree exp, tree_stmt_iterator *tsi)
   tree t, stmt;
 
   t = create_tmp_var_for (info, TREE_TYPE (exp), NULL);
-  stmt = build2 (MODIFY_EXPR, TREE_TYPE (t), t, exp);
+  stmt = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (t), t, exp);
   SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
   tsi_link_before (tsi, stmt, TSI_SAME_STMT);
 
@@ -412,7 +417,7 @@ save_tmp_var (struct nesting_info *info, tree exp,
   tree t, stmt;
 
   t = create_tmp_var_for (info, TREE_TYPE (exp), NULL);
-  stmt = build2 (MODIFY_EXPR, TREE_TYPE (t), exp, t);
+  stmt = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (t), exp, t);
   SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
   tsi_link_after (tsi, stmt, TSI_SAME_STMT);
 
@@ -542,6 +547,47 @@ get_nl_goto_field (struct nesting_info *info)
   return field;
 }
 \f
+/* Helper function for walk_stmts.  Walk output operands of an ASM_EXPR.  */
+
+static void
+walk_asm_expr (struct walk_stmt_info *wi, tree stmt)
+{
+  int noutputs = list_length (ASM_OUTPUTS (stmt));
+  const char **oconstraints
+    = (const char **) alloca ((noutputs) * sizeof (const char *));
+  int i;
+  tree link;
+  const char *constraint;
+  bool allows_mem, allows_reg, is_inout;
+
+  wi->is_lhs = true;
+  for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
+    {
+      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+      oconstraints[i] = constraint;
+      parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
+                              &allows_reg, &is_inout);
+
+      wi->val_only = (allows_reg || !allows_mem);
+      walk_tree (&TREE_VALUE (link), wi->callback, wi, NULL);
+    }
+
+  for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
+    {
+      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+      parse_input_constraint (&constraint, 0, 0, noutputs, 0,
+                             oconstraints, &allows_mem, &allows_reg);
+
+      wi->val_only = (allows_reg || !allows_mem);
+      /* Although input "m" is not really a LHS, we need a lvalue.  */
+      wi->is_lhs = !wi->val_only;
+      walk_tree (&TREE_VALUE (link), wi->callback, wi, NULL);
+    }
+
+  wi->is_lhs = false;
+  wi->val_only = true;
+}
+
 /* Iterate over all sub-statements of *TP calling walk_tree with
    WI->CALLBACK for every sub-expression in each statement found.  */
 
@@ -609,21 +655,25 @@ walk_stmts (struct walk_stmt_info *wi, tree *tp)
       walk_stmts (wi, &TREE_OPERAND (t, 0));
       break;
 
-    case MODIFY_EXPR:
+    case GIMPLE_MODIFY_STMT:
       /* A formal temporary lhs may use a COMPONENT_REF rhs.  */
-      wi->val_only = !is_gimple_formal_tmp_var (TREE_OPERAND (t, 0));
-      walk_tree (&TREE_OPERAND (t, 1), wi->callback, wi, NULL);
+      wi->val_only = !is_gimple_formal_tmp_var (GIMPLE_STMT_OPERAND (t, 0));
+      walk_tree (&GIMPLE_STMT_OPERAND (t, 1), wi->callback, wi, NULL);
 
       /* If the rhs is appropriate for a memory, we may use a
         COMPONENT_REF on the lhs.  */
-      wi->val_only = !is_gimple_mem_rhs (TREE_OPERAND (t, 1));
+      wi->val_only = !is_gimple_mem_rhs (GIMPLE_STMT_OPERAND (t, 1));
       wi->is_lhs = true;
-      walk_tree (&TREE_OPERAND (t, 0), wi->callback, wi, NULL);
+      walk_tree (&GIMPLE_STMT_OPERAND (t, 0), wi->callback, wi, NULL);
 
       wi->val_only = true;
       wi->is_lhs = false;
       break;
 
+    case ASM_EXPR:
+      walk_asm_expr (wi, *tp);
+      break;
+
     default:
       wi->val_only = true;
       walk_tree (tp, wi->callback, wi, NULL);
@@ -1034,9 +1084,10 @@ convert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data)
       save_suppress = info->suppress_expansion;
       if (convert_nonlocal_omp_clauses (&OMP_PARALLEL_CLAUSES (t), wi))
        {
-         tree c;
-         c = get_chain_decl (info);
-         c = build1 (OMP_CLAUSE_FIRSTPRIVATE, void_type_node, c);
+         tree c, decl;
+         decl = get_chain_decl (info);
+         c = build_omp_clause (OMP_CLAUSE_FIRSTPRIVATE);
+         OMP_CLAUSE_DECL (c) = decl;
          OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t);
          OMP_PARALLEL_CLAUSES (t) = c;
        }
@@ -1047,7 +1098,7 @@ convert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data)
       walk_body (convert_nonlocal_reference, info, &OMP_PARALLEL_BODY (t));
 
       if (info->new_local_var_chain)
-       declare_tmp_vars (info->new_local_var_chain, OMP_PARALLEL_BODY (t));
+       declare_vars (info->new_local_var_chain, OMP_PARALLEL_BODY (t), false);
       info->new_local_var_chain = save_local_var_chain;
       info->suppress_expansion = save_suppress;
       break;
@@ -1094,7 +1145,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
 
   for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
     {
-      switch (TREE_CODE (clause))
+      switch (OMP_CLAUSE_CODE (clause))
        {
        case OMP_CLAUSE_PRIVATE:
        case OMP_CLAUSE_FIRSTPRIVATE:
@@ -1119,7 +1170,8 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_NUM_THREADS:
          wi->val_only = true;
          wi->is_lhs = false;
-         convert_nonlocal_reference (&TREE_OPERAND (clause, 0), &dummy, wi);
+         convert_nonlocal_reference (&OMP_CLAUSE_OPERAND (clause, 0), &dummy,
+                                     wi);
          break;
 
        case OMP_CLAUSE_NOWAIT:
@@ -1184,6 +1236,9 @@ get_local_debug_decl (struct nesting_info *info, tree decl, tree field)
   TREE_CHAIN (new_decl) = info->debug_var_chain;
   info->debug_var_chain = new_decl;
 
+  /* Do not emit debug info twice.  */
+  DECL_IGNORED_P (decl) = 1;
+
   return new_decl;
 }
 
@@ -1317,7 +1372,8 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
        {
          tree c;
          (void) get_frame_type (info);
-         c = build1 (OMP_CLAUSE_SHARED, void_type_node, info->frame_decl);
+         c = build_omp_clause (OMP_CLAUSE_SHARED);
+         OMP_CLAUSE_DECL (c) = info->frame_decl;
          OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t);
          OMP_PARALLEL_CLAUSES (t) = c;
        }
@@ -1328,7 +1384,7 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
       walk_body (convert_local_reference, info, &OMP_PARALLEL_BODY (t));
 
       if (info->new_local_var_chain)
-       declare_tmp_vars (info->new_local_var_chain, OMP_PARALLEL_BODY (t));
+       declare_vars (info->new_local_var_chain, OMP_PARALLEL_BODY (t), false);
       info->new_local_var_chain = save_local_var_chain;
       info->suppress_expansion = save_suppress;
       break;
@@ -1375,7 +1431,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
 
   for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
     {
-      switch (TREE_CODE (clause))
+      switch (OMP_CLAUSE_CODE (clause))
        {
        case OMP_CLAUSE_PRIVATE:
        case OMP_CLAUSE_FIRSTPRIVATE:
@@ -1406,7 +1462,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_NUM_THREADS:
          wi->val_only = true;
          wi->is_lhs = false;
-         convert_local_reference (&TREE_OPERAND (clause, 0), &dummy, wi);
+         convert_local_reference (&OMP_CLAUSE_OPERAND (clause, 0), &dummy, wi);
          break;
 
        case OMP_CLAUSE_NOWAIT:
@@ -1617,6 +1673,8 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data)
   struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
   struct nesting_info *info = wi->info;
   tree t = *tp, decl, target_context;
+  char save_static_chain_added;
+  int i;
 
   *walk_subtrees = 0;
   switch (TREE_CODE (t))
@@ -1627,19 +1685,51 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data)
        break;
       target_context = decl_function_context (decl);
       if (target_context && !DECL_NO_STATIC_CHAIN (decl))
-       TREE_OPERAND (t, 2)
-         = get_static_chain (info, target_context, &wi->tsi);
+       {
+         TREE_OPERAND (t, 2)
+           = get_static_chain (info, target_context, &wi->tsi);
+         info->static_chain_added
+           |= (1 << (info->context != target_context));
+       }
       break;
 
     case RETURN_EXPR:
-    case MODIFY_EXPR:
+    case GIMPLE_MODIFY_STMT:
     case WITH_SIZE_EXPR:
       /* Only return modify and with_size_expr may contain calls.  */
       *walk_subtrees = 1;
       break;
 
+    case OMP_PARALLEL:
+      save_static_chain_added = info->static_chain_added;
+      info->static_chain_added = 0;
+      walk_body (convert_call_expr, info, &OMP_PARALLEL_BODY (t));
+      for (i = 0; i < 2; i++)
+       {
+         tree c, decl;
+         if ((info->static_chain_added & (1 << i)) == 0)
+           continue;
+         decl = i ? get_chain_decl (info) : info->frame_decl;
+         /* Don't add CHAIN.* or FRAME.* twice.  */
+         for (c = OMP_PARALLEL_CLAUSES (t); c; c = OMP_CLAUSE_CHAIN (c))
+           if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+                || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
+               && OMP_CLAUSE_DECL (c) == decl)
+             break;
+         if (c == NULL)
+           {
+             c = build_omp_clause (OMP_CLAUSE_FIRSTPRIVATE);
+             OMP_CLAUSE_DECL (c) = decl;
+             OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t);
+             OMP_PARALLEL_CLAUSES (t) = c;
+           }
+       }
+      info->static_chain_added |= save_static_chain_added;
+      break;
+
     case OMP_FOR:
     case OMP_SECTIONS:
+    case OMP_SECTION:
     case OMP_SINGLE:
     case OMP_MASTER:
     case OMP_ORDERED:
@@ -1726,7 +1816,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
 
          y = build3 (COMPONENT_REF, TREE_TYPE (field),
                      root->frame_decl, field, NULL_TREE);
-         x = build2 (MODIFY_EXPR, TREE_TYPE (field), y, x);
+         x = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (field), y, x);
          append_to_statement_list (x, &stmt_list);
        }
     }
@@ -1737,7 +1827,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
     {
       tree x = build3 (COMPONENT_REF, TREE_TYPE (root->chain_field),
                       root->frame_decl, root->chain_field, NULL_TREE);
-      x = build2 (MODIFY_EXPR, TREE_TYPE (x), x, get_chain_decl (root));
+      x = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (x), x, get_chain_decl (root));
       append_to_statement_list (x, &stmt_list);
     }
 
@@ -1801,11 +1891,11 @@ finalize_nesting_tree_1 (struct nesting_info *root)
   /* Make sure all new local variables get inserted into the
      proper BIND_EXPR.  */
   if (root->new_local_var_chain)
-    declare_tmp_vars (root->new_local_var_chain,
-                     DECL_SAVED_TREE (root->context));
+    declare_vars (root->new_local_var_chain, DECL_SAVED_TREE (root->context),
+                 false);
   if (root->debug_var_chain)
-    declare_tmp_vars (root->debug_var_chain,
-                     DECL_SAVED_TREE (root->context));
+    declare_vars (root->debug_var_chain, DECL_SAVED_TREE (root->context),
+                 true);
 
   /* Dump the translated tree function.  */
   dump_function (TDI_nested, root->context);