summaryrefslogtreecommitdiff
path: root/gcc/tree-nested.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2009-04-26 18:47:54 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2009-04-26 18:47:54 +0000
commit9579733ed5bf9976b201cbe8cc2649ea033987bc (patch)
tree2115d30581d9d9182f2b8de566ba08dcd3742e3b /gcc/tree-nested.c
parent1938132c01eff0ee84005dbd15e6bbf553d5f7ec (diff)
downloadgcc-9579733ed5bf9976b201cbe8cc2649ea033987bc.tar.gz
* tree-nested.c (get_nonlocal_vla_type): If not optimizing, call
note_nonlocal_vla_type for nonlocal VLAs. (note_nonlocal_vla_type, note_nonlocal_block_vlas, contains_remapped_vars, remap_vla_decls): New functions. (convert_nonlocal_reference_stmt): If not optimizing, call note_nonlocal_block_vlas on GIMPLE_BIND block vars. (nesting_copy_decl): Return {VAR,PARM,RESULT}_DECL unmodified if it wasn't found in var_map. (finalize_nesting_tree_1): Call remap_vla_decls. If outermost GIMPLE_BIND doesn't have gimple_bind_block, chain debug_var_chain to BLOCK_VARS (DECL_INITIAL (root->context)) instead of calling declare_vars. * gimplify.c (nonlocal_vlas): New variable. (gimplify_var_or_parm_decl): Add debug VAR_DECLs for non-local referenced VLAs. (gimplify_body): Create and destroy nonlocal_vlas. * trans-decl.c: Include pointer-set.h. (nonlocal_dummy_decl_pset, tree nonlocal_dummy_decls): New variables. (gfc_nonlocal_dummy_array_decl): New function. (gfc_get_symbol_decl): Call it for non-local dummy args with saved descriptor. (gfc_get_symbol_decl): Set DECL_BY_REFERENCE when needed. (gfc_generate_function_code): Initialize nonlocal_dummy_decl{s,_pset}, chain it to outermost block's vars, destroy it afterwards. * Make-lang.in (trans-decl.o): Depend on pointer-set.h. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@146810 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-nested.c')
-rw-r--r--gcc/tree-nested.c188
1 files changed, 185 insertions, 3 deletions
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index b3301a712a8..e45f8de2532 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -770,6 +770,7 @@ get_frame_field (struct nesting_info *info, tree target_context,
return x;
}
+static void note_nonlocal_vla_type (struct nesting_info *info, tree type);
/* A subroutine of convert_nonlocal_reference_op. Create a local variable
in the nested function with DECL_VALUE_EXPR set to reference the true
@@ -840,6 +841,11 @@ get_nonlocal_debug_decl (struct nesting_info *info, tree decl)
TREE_CHAIN (new_decl) = info->debug_var_chain;
info->debug_var_chain = new_decl;
+ if (!optimize
+ && info->context != target_context
+ && variably_modified_type_p (TREE_TYPE (decl), NULL))
+ note_nonlocal_vla_type (info, TREE_TYPE (decl));
+
return new_decl;
}
@@ -1111,6 +1117,60 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
return need_chain;
}
+/* Create nonlocal debug decls for nonlocal VLA array bounds. */
+
+static void
+note_nonlocal_vla_type (struct nesting_info *info, tree type)
+{
+ while (POINTER_TYPE_P (type) && !TYPE_NAME (type))
+ type = TREE_TYPE (type);
+
+ if (TYPE_NAME (type)
+ && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
+ type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
+
+ while (POINTER_TYPE_P (type)
+ || TREE_CODE (type) == VECTOR_TYPE
+ || TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ type = TREE_TYPE (type);
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ tree domain, t;
+
+ note_nonlocal_vla_type (info, TREE_TYPE (type));
+ domain = TYPE_DOMAIN (type);
+ if (domain)
+ {
+ t = TYPE_MIN_VALUE (domain);
+ if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
+ && decl_function_context (t) != info->context)
+ get_nonlocal_debug_decl (info, t);
+ t = TYPE_MAX_VALUE (domain);
+ if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
+ && decl_function_context (t) != info->context)
+ get_nonlocal_debug_decl (info, t);
+ }
+ }
+}
+
+/* Create nonlocal debug decls for nonlocal VLA array bounds for VLAs
+ in BLOCK. */
+
+static void
+note_nonlocal_block_vlas (struct nesting_info *info, tree block)
+{
+ tree var;
+
+ 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)
+ && decl_function_context (var) != info->context)
+ note_nonlocal_vla_type (info, TREE_TYPE (var));
+}
/* Callback for walk_gimple_stmt. Rewrite all references to VAR and
PARM_DECLs that belong to outer functions. This handles statements
@@ -1202,6 +1262,13 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
info, gimple_omp_body (stmt));
break;
+ case GIMPLE_BIND:
+ if (!optimize && gimple_bind_block (stmt))
+ note_nonlocal_block_vlas (info, gimple_bind_block (stmt));
+
+ *handled_ops_p = false;
+ return NULL_TREE;
+
default:
/* For every other statement that we are not interested in
handling here, let the walker traverse the operands. */
@@ -1979,9 +2046,117 @@ nesting_copy_decl (tree decl, copy_body_data *id)
return new_decl;
}
+ if (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == PARM_DECL
+ || TREE_CODE (decl) == RESULT_DECL)
+ return decl;
+
return copy_decl_no_change (decl, id);
}
+/* A helper function for remap_vla_decls. See if *TP contains
+ some remapped variables. */
+
+static tree
+contains_remapped_vars (tree *tp, int *walk_subtrees, void *data)
+{
+ struct nesting_info *root = (struct nesting_info *) data;
+ tree t = *tp;
+ void **slot;
+
+ if (DECL_P (t))
+ {
+ *walk_subtrees = 0;
+ slot = pointer_map_contains (root->var_map, t);
+
+ if (slot)
+ return (tree) *slot;
+ }
+ return NULL;
+}
+
+/* Remap VLA decls in BLOCK and subblocks if remapped variables are
+ involved. */
+
+static void
+remap_vla_decls (tree block, struct nesting_info *root)
+{
+ tree var, subblock, val, type;
+ struct nesting_copy_body_data id;
+
+ for (subblock = BLOCK_SUBBLOCKS (block);
+ subblock;
+ 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;
+ }
+ }
+ if (var == NULL_TREE)
+ return;
+
+ memset (&id, 0, sizeof (id));
+ id.cb.copy_decl = nesting_copy_decl;
+ 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))
+ {
+ struct nesting_info *i;
+ tree newt, t, context;
+
+ 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)
+ continue;
+
+ context = decl_function_context (var);
+ for (i = root; i; i = i->outer)
+ if (i->context == context)
+ break;
+
+ if (i == NULL)
+ continue;
+
+ id.cb.src_fn = i->context;
+ id.cb.dst_fn = i->context;
+ id.cb.src_cfun = DECL_STRUCT_FUNCTION (root->context);
+
+ TREE_TYPE (var) = newt = remap_type (type, &id.cb);
+ while (POINTER_TYPE_P (newt) && !TYPE_NAME (newt))
+ {
+ newt = TREE_TYPE (newt);
+ t = TREE_TYPE (t);
+ }
+ 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))
+ TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb);
+
+ walk_tree (&val, copy_tree_body_r, &id.cb, NULL);
+ if (val != DECL_VALUE_EXPR (var))
+ SET_DECL_VALUE_EXPR (var, val);
+ }
+
+ pointer_map_destroy (id.cb.decl_map);
+}
+
/* Do "everything else" to clean up or complete state collected by the
various walking passes -- lay out the types and decls, generate code
to initialize the frame decl, store critical expressions in the
@@ -2118,6 +2293,9 @@ finalize_nesting_tree_1 (struct nesting_info *root)
if (root->debug_var_chain)
{
tree debug_var;
+ gimple scope;
+
+ remap_vla_decls (DECL_INITIAL (root->context), root);
for (debug_var = root->debug_var_chain; debug_var;
debug_var = TREE_CHAIN (debug_var))
@@ -2170,9 +2348,13 @@ finalize_nesting_tree_1 (struct nesting_info *root)
pointer_map_destroy (id.cb.decl_map);
}
- declare_vars (root->debug_var_chain,
- gimple_seq_first_stmt (gimple_body (root->context)),
- true);
+ scope = gimple_seq_first_stmt (gimple_body (root->context));
+ if (gimple_bind_block (scope))
+ declare_vars (root->debug_var_chain, scope, true);
+ else
+ BLOCK_VARS (DECL_INITIAL (root->context))
+ = chainon (BLOCK_VARS (DECL_INITIAL (root->context)),
+ root->debug_var_chain);
}
/* Dump the translated tree function. */