OSDN Git Service

2011-09-01 Romain Berrendonner <berrendo@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-nested.c
index 81ae38f..ef51ff4 100644 (file)
@@ -184,7 +184,7 @@ build_addr (tree exp, tree context)
      way the properties are for the ADDR_EXPR are computed properly.  */
   save_context = current_function_decl;
   current_function_decl = context;
-  retval = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
+  retval = build_fold_addr_expr (exp);
   current_function_decl = save_context;
   return retval;
 }
@@ -486,7 +486,7 @@ get_trampoline_type (struct nesting_info *info)
       align = STACK_BOUNDARY;
     }
 
-  t = build_index_type (build_int_cst (NULL_TREE, size - 1));
+  t = build_index_type (size_int (size - 1));
   t = build_array_type (char_type_node, t);
   t = build_decl (DECL_SOURCE_LOCATION (info->context),
                  FIELD_DECL, get_identifier ("__data"), t);
@@ -561,7 +561,7 @@ get_nl_goto_field (struct nesting_info *info)
       size = size + 1;
 
       type = build_array_type
-       (type, build_index_type (build_int_cst (NULL_TREE, size)));
+       (type, build_index_type (size_int (size)));
 
       field = make_node (FIELD_DECL);
       DECL_NAME (field) = get_identifier ("__nl_goto_buf");
@@ -693,7 +693,7 @@ walk_all_functions (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
 static bool
 check_for_nested_with_variably_modified (tree fndecl, tree orig_fndecl)
 {
-  struct cgraph_node *cgn = cgraph_node (fndecl);
+  struct cgraph_node *cgn = cgraph_get_node (fndecl);
   tree arg;
 
   for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
@@ -1097,6 +1097,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
          if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL)
            break;
          /* FALLTHRU */
+       case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_IF:
        case OMP_CLAUSE_NUM_THREADS:
          wi->val_only = true;
@@ -1111,6 +1112,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_COLLAPSE:
        case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        default:
@@ -1594,6 +1596,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
          if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL)
            break;
          /* FALLTHRU */
+       case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_IF:
        case OMP_CLAUSE_NUM_THREADS:
          wi->val_only = true;
@@ -1608,6 +1611,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_COLLAPSE:
        case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        default:
@@ -2070,9 +2074,8 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 static void
 convert_all_function_calls (struct nesting_info *root)
 {
+  unsigned int chain_count = 0, old_chain_count, iter_count;
   struct nesting_info *n;
-  int iter_count;
-  bool any_changed;
 
   /* First, optimistically clear static_chain for all decls that haven't
      used the static chain already for variable access.  */
@@ -2088,6 +2091,7 @@ convert_all_function_calls (struct nesting_info *root)
        }
       else
        DECL_STATIC_CHAIN (decl) = 1;
+      chain_count += DECL_STATIC_CHAIN (decl);
     }
 
   /* Walk the functions and perform transformations.  Note that these
@@ -2100,7 +2104,8 @@ convert_all_function_calls (struct nesting_info *root)
   iter_count = 0;
   do
     {
-      any_changed = false;
+      old_chain_count = chain_count;
+      chain_count = 0;
       iter_count++;
 
       if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2109,22 +2114,16 @@ convert_all_function_calls (struct nesting_info *root)
       FOR_EACH_NEST_INFO (n, root)
        {
          tree decl = n->context;
-         bool old_static_chain = DECL_STATIC_CHAIN (decl);
-
          walk_function (convert_tramp_reference_stmt,
                         convert_tramp_reference_op, n);
          walk_function (convert_gimple_call, NULL, n);
-
-         /* If a call to another function created the use of a chain
-            within this function, we'll have to continue iteration.  */
-         if (!old_static_chain && DECL_STATIC_CHAIN (decl))
-           any_changed = true;
+         chain_count += DECL_STATIC_CHAIN (decl);
        }
     }
-  while (any_changed);
+  while (chain_count != old_chain_count);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
-    fprintf (dump_file, "convert_all_function_calls iterations: %d\n\n",
+    fprintf (dump_file, "convert_all_function_calls iterations: %u\n\n",
             iter_count);
 }
 
@@ -2197,18 +2196,21 @@ remap_vla_decls (tree block, struct nesting_info *root)
     remap_vla_decls (subblock, root);
 
   for (var = BLOCK_VARS (block); var; var = DECL_CHAIN (var))
-    {
-      if (TREE_CODE (var) == VAR_DECL
-         && variably_modified_type_p (TREE_TYPE (var), NULL)
-         && DECL_HAS_VALUE_EXPR_P (var))
-       {
-         type = TREE_TYPE (var);
-         val = DECL_VALUE_EXPR (var);
-         if (walk_tree (&type, contains_remapped_vars, root, NULL) != NULL
-             ||  walk_tree (&val, contains_remapped_vars, root, NULL) != NULL)
-           break;
-       }
-    }
+    if (TREE_CODE (var) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (var))
+      {
+       val = DECL_VALUE_EXPR (var);
+       type = TREE_TYPE (var);
+
+       if (!(TREE_CODE (val) == INDIRECT_REF
+             && TREE_CODE (TREE_OPERAND (val, 0)) == VAR_DECL
+             && variably_modified_type_p (type, NULL)))
+         continue;
+
+       if (pointer_map_contains (root->var_map, TREE_OPERAND (val, 0))
+           || walk_tree (&type, contains_remapped_vars, root, NULL))
+         break;
+      }
+
   if (var == NULL_TREE)
     return;
 
@@ -2218,17 +2220,22 @@ remap_vla_decls (tree block, struct nesting_info *root)
   id.root = root;
 
   for (; var; var = DECL_CHAIN (var))
-    if (TREE_CODE (var) == VAR_DECL
-       && variably_modified_type_p (TREE_TYPE (var), NULL)
-       && DECL_HAS_VALUE_EXPR_P (var))
+    if (TREE_CODE (var) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (var))
       {
        struct nesting_info *i;
-       tree newt, t, context;
+       tree newt, context;
+       void **slot;
 
-       t = type = TREE_TYPE (var);
        val = DECL_VALUE_EXPR (var);
-       if (walk_tree (&type, contains_remapped_vars, root, NULL) == NULL
-           && walk_tree (&val, contains_remapped_vars, root, NULL) == NULL)
+       type = TREE_TYPE (var);
+
+       if (!(TREE_CODE (val) == INDIRECT_REF
+             && TREE_CODE (TREE_OPERAND (val, 0)) == VAR_DECL
+             && variably_modified_type_p (type, NULL)))
+         continue;
+
+       slot = pointer_map_contains (root->var_map, TREE_OPERAND (val, 0));
+       if (!slot && !walk_tree (&type, contains_remapped_vars, root, NULL))
          continue;
 
        context = decl_function_context (var);
@@ -2239,6 +2246,15 @@ remap_vla_decls (tree block, struct nesting_info *root)
        if (i == NULL)
          continue;
 
+       /* Fully expand value expressions.  This avoids having debug variables
+          only referenced from them and that can be swept during GC.  */
+        if (slot)
+         {
+           tree t = (tree) *slot;
+           gcc_assert (DECL_P (t) && DECL_HAS_VALUE_EXPR_P (t));
+           val = build1 (INDIRECT_REF, TREE_TYPE (val), DECL_VALUE_EXPR (t));
+         }
+
        id.cb.src_fn = i->context;
        id.cb.dst_fn = i->context;
        id.cb.src_cfun = DECL_STRUCT_FUNCTION (root->context);
@@ -2247,13 +2263,13 @@ remap_vla_decls (tree block, struct nesting_info *root)
        while (POINTER_TYPE_P (newt) && !TYPE_NAME (newt))
          {
            newt = TREE_TYPE (newt);
-           t = TREE_TYPE (t);
+           type = TREE_TYPE (type);
          }
        if (TYPE_NAME (newt)
            && TREE_CODE (TYPE_NAME (newt)) == TYPE_DECL
            && DECL_ORIGINAL_TYPE (TYPE_NAME (newt))
-           && newt != t
-           && TYPE_NAME (newt) == TYPE_NAME (t))
+           && newt != type
+           && TYPE_NAME (newt) == TYPE_NAME (type))
          TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb);
 
        walk_tree (&val, copy_tree_body_r, &id.cb, NULL);
@@ -2511,13 +2527,13 @@ finalize_nesting_tree (struct nesting_info *root)
 static void
 unnest_nesting_tree_1 (struct nesting_info *root)
 {
-  struct cgraph_node *node = cgraph_node (root->context);
+  struct cgraph_node *node = cgraph_get_node (root->context);
 
   /* For nested functions update the cgraph to reflect unnesting.
      We also delay finalizing of these functions up to this point.  */
   if (node->origin)
     {
-       cgraph_unnest_node (cgraph_node (root->context));
+       cgraph_unnest_node (node);
        cgraph_finalize_function (root->context, true);
     }
 }
@@ -2571,7 +2587,7 @@ lower_nested_functions (tree fndecl)
   struct nesting_info *root;
 
   /* If there are no nested functions, there's nothing to do.  */
-  cgn = cgraph_node (fndecl);
+  cgn = cgraph_get_node (fndecl);
   if (!cgn->nested)
     return;