OSDN Git Service

PR libgcj/49315
[pf3gnuchains/gcc-fork.git] / gcc / tree-nested.c
index db704b7..1b26eca 100644 (file)
@@ -148,7 +148,7 @@ create_tmp_var_for (struct nesting_info *info, tree type, const char *prefix)
 
   tmp_var = create_tmp_var_raw (type, prefix);
   DECL_CONTEXT (tmp_var) = info->context;
-  TREE_CHAIN (tmp_var) = info->new_local_var_chain;
+  DECL_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)
@@ -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;
 }
@@ -198,11 +198,11 @@ insert_field_into_struct (tree type, tree field)
 
   DECL_CONTEXT (field) = type;
 
-  for (p = &TYPE_FIELDS (type); *p ; p = &TREE_CHAIN (*p))
+  for (p = &TYPE_FIELDS (type); *p ; p = &DECL_CHAIN (*p))
     if (DECL_ALIGN (field) >= DECL_ALIGN (*p))
       break;
 
-  TREE_CHAIN (field) = *p;
+  DECL_CHAIN (field) = *p;
   *p = field;
 
   /* Set correct alignment for frame struct type.  */
@@ -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,12 +693,12 @@ 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)
     {
-      for (arg = DECL_ARGUMENTS (cgn->decl); arg; arg = TREE_CHAIN (arg))
+      for (arg = DECL_ARGUMENTS (cgn->decl); arg; arg = DECL_CHAIN (arg))
        if (variably_modified_type_p (TREE_TYPE (arg), orig_fndecl))
          return true;
 
@@ -875,7 +875,7 @@ get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
   DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
 
   *slot = new_decl;
-  TREE_CHAIN (new_decl) = info->debug_var_chain;
+  DECL_CHAIN (new_decl) = info->debug_var_chain;
   info->debug_var_chain = new_decl;
 
   if (!optimize
@@ -1202,7 +1202,7 @@ note_nonlocal_block_vlas (struct nesting_info *info, tree block)
 {
   tree var;
 
-  for (var = BLOCK_VARS (block); var; var = TREE_CHAIN (var))
+  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)
@@ -1367,7 +1367,7 @@ get_local_debug_decl (struct nesting_info *info, tree decl, tree field)
   DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
   *slot = new_decl;
 
-  TREE_CHAIN (new_decl) = info->debug_var_chain;
+  DECL_CHAIN (new_decl) = info->debug_var_chain;
   info->debug_var_chain = new_decl;
 
   /* Do not emit debug info twice.  */
@@ -2070,9 +2070,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 +2087,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 +2100,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 +2110,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);
 }
 
@@ -2196,19 +2191,22 @@ remap_vla_decls (tree block, struct nesting_info *root)
        subblock = BLOCK_CHAIN (subblock))
     remap_vla_decls (subblock, root);
 
-  for (var = BLOCK_VARS (block); var; var = TREE_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;
-       }
-    }
+  for (var = BLOCK_VARS (block); var; var = DECL_CHAIN (var))
+    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;
 
@@ -2217,18 +2215,23 @@ remap_vla_decls (tree block, struct nesting_info *root)
   id.cb.decl_map = pointer_map_create ();
   id.root = root;
 
-  for (; var; var = TREE_CHAIN (var))
-    if (TREE_CODE (var) == VAR_DECL
-       && variably_modified_type_p (TREE_TYPE (var), NULL)
-       && DECL_HAS_VALUE_EXPR_P (var))
+  for (; var; var = DECL_CHAIN (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 +2242,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 +2259,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);
@@ -2308,11 +2320,11 @@ finalize_nesting_tree_1 (struct nesting_info *root)
         expression get substituted in instantiate_virtual_regs().  */
       for (adjust = &root->new_local_var_chain;
           *adjust != root->frame_decl;
-          adjust = &TREE_CHAIN (*adjust))
-       gcc_assert (TREE_CHAIN (*adjust));
-      *adjust = TREE_CHAIN (*adjust);
+          adjust = &DECL_CHAIN (*adjust))
+       gcc_assert (DECL_CHAIN (*adjust));
+      *adjust = DECL_CHAIN (*adjust);
 
-      TREE_CHAIN (root->frame_decl) = NULL_TREE;
+      DECL_CHAIN (root->frame_decl) = NULL_TREE;
       declare_vars (root->frame_decl,
                    gimple_seq_first_stmt (gimple_body (context)), true);
     }
@@ -2323,7 +2335,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
   if (root->any_parm_remapped)
     {
       tree p;
-      for (p = DECL_ARGUMENTS (context); p ; p = TREE_CHAIN (p))
+      for (p = DECL_ARGUMENTS (context); p ; p = DECL_CHAIN (p))
        {
          tree field, x, y;
 
@@ -2428,7 +2440,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
       remap_vla_decls (DECL_INITIAL (root->context), root);
 
       for (debug_var = root->debug_var_chain; debug_var;
-          debug_var = TREE_CHAIN (debug_var))
+          debug_var = DECL_CHAIN (debug_var))
        if (variably_modified_type_p (TREE_TYPE (debug_var), NULL))
          break;
 
@@ -2443,7 +2455,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
          id.cb.decl_map = pointer_map_create ();
          id.root = root;
 
-         for (; debug_var; debug_var = TREE_CHAIN (debug_var))
+         for (; debug_var; debug_var = DECL_CHAIN (debug_var))
            if (variably_modified_type_p (TREE_TYPE (debug_var), NULL))
              {
                tree type = TREE_TYPE (debug_var);
@@ -2511,13 +2523,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 +2583,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;