#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)
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;
}
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);
}
}
{
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
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. */
}
else
DECL_STATIC_CHAIN (decl) = 1;
+ chain_count += DECL_STATIC_CHAIN (decl);
}
/* Walk the functions and perform transformations. Note that these
iter_count = 0;
do
{
- any_changed = false;
+ old_chain_count = chain_count;
+ chain_count = 0;
iter_count++;
if (dump_file && (dump_flags & TDF_DETAILS))
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);
}
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;
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);
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);
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);
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;
}