/* Nested function decomposition for GIMPLE.
- Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
+ Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GCC.
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "rtl.h"
#include "tm_p.h"
#include "function.h"
#include "tree-dump.h"
#include "tree-iterator.h"
#include "tree-flow.h"
#include "cgraph.h"
-#include "expr.h"
+#include "expr.h" /* FIXME: For STACK_SAVEAREA_MODE and SAVE_NONLOCAL. */
#include "langhooks.h"
#include "pointer-set.h"
-#include "ggc.h"
/* The object of this pass is to lower the representation of a set of nested
struct pointer_map_t *field_map;
struct pointer_map_t *var_map;
+ struct pointer_set_t *mem_refs;
bitmap suppress_expansion;
tree context;
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)
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. */
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;
struct nesting_info *info = XCNEW (struct nesting_info);
info->field_map = pointer_map_create ();
info->var_map = pointer_map_create ();
+ info->mem_refs = pointer_set_create ();
info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack);
info->context = cgn->decl;
{
tree field = get_chain_field (i);
- x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+ x = build_simple_mem_ref (x);
x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
x = init_tmp_var (info, x, gsi);
}
{
tree field = get_chain_field (i);
- x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+ x = build_simple_mem_ref (x);
x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
x = init_tmp_var (info, x, gsi);
}
- x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+ x = build_simple_mem_ref (x);
}
x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
for (i = info->outer; i->context != target_context; i = i->outer)
{
field = get_chain_field (i);
- x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+ x = build_simple_mem_ref (x);
x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
}
- x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+ x = build_simple_mem_ref (x);
}
field = lookup_field_for_decl (i, decl, INSERT);
x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
if (use_pointer_in_frame (decl))
- x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+ x = build_simple_mem_ref (x);
/* ??? We should be remapping types as well, surely. */
new_decl = build_decl (DECL_SOURCE_LOCATION (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
if (use_pointer_in_frame (t))
{
x = init_tmp_var (info, x, &wi->gsi);
- x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
+ x = build_simple_mem_ref (x);
}
}
{
bitmap_set_bit (new_suppress, DECL_UID (decl));
OMP_CLAUSE_DECL (clause) = get_nonlocal_debug_decl (info, decl);
- need_chain = true;
+ if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_PRIVATE)
+ need_chain = true;
}
break;
{
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)
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. */
wi->val_only = save_val_only;
break;
+ case MEM_REF:
+ save_val_only = wi->val_only;
+ wi->val_only = true;
+ wi->is_lhs = false;
+ walk_tree (&TREE_OPERAND (t, 0), convert_local_reference_op,
+ wi, NULL);
+ /* We need to re-fold the MEM_REF as component references as
+ part of a ADDR_EXPR address are not allowed. But we cannot
+ fold here, as the chain record type is not yet finalized. */
+ if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
+ && !DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
+ pointer_set_insert (info->mem_refs, tp);
+ wi->val_only = save_val_only;
+ break;
+
case VIEW_CONVERT_EXPR:
/* Just request to look at the subtrees, leaving val_only and lhs
untouched. This might actually be for !val_only + lhs, in which
subblock = BLOCK_CHAIN (subblock))
remap_vla_decls (subblock, root);
- 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)
id.cb.decl_map = pointer_map_create ();
id.root = root;
- for (; var; var = TREE_CHAIN (var))
+ 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))
pointer_map_destroy (id.cb.decl_map);
}
+/* Fold the MEM_REF *E. */
+static bool
+fold_mem_refs (const void *e, void *data ATTRIBUTE_UNUSED)
+{
+ tree *ref_p = CONST_CAST2(tree *, const tree *, (const tree *)e);
+ *ref_p = fold (*ref_p);
+ return true;
+}
+
/* 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
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);
}
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;
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;
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);
root->debug_var_chain);
}
+ /* Fold the rewritten MEM_REF trees. */
+ pointer_set_traverse (root->mem_refs, fold_mem_refs, NULL);
+
/* Dump the translated tree function. */
if (dump_file)
{
next = iter_nestinfo_next (node);
pointer_map_destroy (node->var_map);
pointer_map_destroy (node->field_map);
+ pointer_set_destroy (node->mem_refs);
free (node);
node = next;
}