/* Tree based points-to analysis
- Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
Contributed by Daniel Berlin <dberlin@dberlin.org>
This file is part of GCC.
}
}
- /* Add edges from STOREDANYTHING to all non-direct nodes. */
+ /* Add edges from STOREDANYTHING to all non-direct nodes that can
+ receive pointers. */
t = find (storedanything_id);
for (i = integer_id + 1; i < FIRST_REF_NODE; ++i)
{
- if (!TEST_BIT (graph->direct_nodes, i))
+ if (!TEST_BIT (graph->direct_nodes, i)
+ && get_varinfo (i)->may_have_pointers)
add_graph_edge (graph, find (i), t);
}
+
+ /* Everything stored to ANYTHING also potentially escapes. */
+ add_graph_edge (graph, find (escaped_id), t);
}
&& si->dfs[VEC_last (unsigned, si->scc_stack)] >= my_dfs)
{
bitmap scc = BITMAP_ALLOC (NULL);
- bool have_ref_node = n >= FIRST_REF_NODE;
unsigned int lowest_node;
bitmap_iterator bi;
unsigned int w = VEC_pop (unsigned, si->scc_stack);
bitmap_set_bit (scc, w);
- if (w >= FIRST_REF_NODE)
- have_ref_node = true;
}
lowest_node = bitmap_first_set_bit (scc);
changed_count++;
}
}
-
+
BITMAP_FREE (get_varinfo (from)->solution);
BITMAP_FREE (get_varinfo (from)->oldsolution);
-
+
if (stats.iterations > 0)
{
BITMAP_FREE (get_varinfo (to)->oldsolution);
if (label)
{
int label_rep = graph->pe_rep[label];
-
+
if (label_rep == -1)
continue;
-
+
label_rep = find (label_rep);
if (label_rep >= 0 && unite (label_rep, find (i)))
unify_nodes (graph, label_rep, i, false);
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
-
+
fprintf (dump_file, "%s is a non-pointer variable,"
"ignoring constraint:",
get_varinfo (lhs.var)->name);
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
-
+
fprintf (dump_file, "%s is a non-pointer variable,"
"ignoring constraint:",
get_varinfo (rhs.var)->name);
/* If we are not taking the address of the constraint expr, add all
sub-fiels of the variable as well. */
- if (!address_p)
+ if (!address_p
+ && !vi->is_full_var)
{
for (; vi; vi = vi->next)
{
&& (rhsp->type == SCALAR
|| rhsp->type == ADDRESSOF))
{
- tree lhsbase, rhsbase;
HOST_WIDE_INT lhssize, lhsmaxsize, lhsoffset;
HOST_WIDE_INT rhssize, rhsmaxsize, rhsoffset;
unsigned k = 0;
- lhsbase = get_ref_base_and_extent (lhsop, &lhsoffset,
- &lhssize, &lhsmaxsize);
- rhsbase = get_ref_base_and_extent (rhsop, &rhsoffset,
- &rhssize, &rhsmaxsize);
+ get_ref_base_and_extent (lhsop, &lhsoffset, &lhssize, &lhsmaxsize);
+ get_ref_base_and_extent (rhsop, &rhsoffset, &rhssize, &rhsmaxsize);
for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp);)
{
varinfo_t lhsv, rhsv;
the LHS point to global and escaped variables. */
static void
-handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc)
+handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc, tree fndecl)
{
VEC(ce_s, heap) *lhsc = NULL;
it escapes. */
DECL_EXTERNAL (vi->decl) = 0;
vi->is_global_var = 0;
+ /* If this is not a real malloc call assume the memory was
+ initialized and thus may point to global memory. All
+ builtin functions with the malloc attribute behave in a sane way. */
+ if (!fndecl
+ || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
+ make_constraint_from (vi, nonlocal_id);
}
else if (VEC_length (ce_s, rhsc) > 0)
{
get_constraint_for (gimple_phi_result (t), &lhsc);
for (i = 0; i < gimple_phi_num_args (t); i++)
{
- tree rhstype;
tree strippedrhs = PHI_ARG_DEF (t, i);
STRIP_NOPS (strippedrhs);
- rhstype = TREE_TYPE (strippedrhs);
get_constraint_for (gimple_phi_arg_def (t, i), &rhsc);
for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
handle_rhs_call (t, &rhsc);
if (gimple_call_lhs (t)
&& could_have_pointers (gimple_call_lhs (t)))
- handle_lhs_call (gimple_call_lhs (t), flags, rhsc);
+ handle_lhs_call (gimple_call_lhs (t), flags, rhsc, fndecl);
VEC_free (ce_s, heap, rhsc);
}
else
In that case, however, offset should still be within the size
of the variable. */
if (offset >= start->offset
- && offset < (start->offset + start->size))
+ && (offset - start->offset) < start->size)
return start;
start= start->next;
directly preceding offset which may be the last field. */
while (start->next
&& offset >= start->offset
- && !(offset < (start->offset + start->size)))
+ && !((offset - start->offset) < start->size))
start = start->next;
return start;
static unsigned int
count_num_arguments (tree decl, bool *is_varargs)
{
- unsigned int i = 0;
+ unsigned int num = 0;
tree t;
- for (t = TYPE_ARG_TYPES (TREE_TYPE (decl));
- t;
- t = TREE_CHAIN (t))
- {
- if (TREE_VALUE (t) == void_type_node)
- break;
- i++;
- }
+ /* Capture named arguments for K&R functions. They do not
+ have a prototype and thus no TYPE_ARG_TYPES. */
+ for (t = DECL_ARGUMENTS (decl); t; t = TREE_CHAIN (t))
+ ++num;
+ /* Check if the function has variadic arguments. */
+ for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
+ if (TREE_VALUE (t) == void_type_node)
+ break;
if (!t)
*is_varargs = true;
- return i;
+
+ return num;
}
/* Creation function node for DECL, using NAME, and return the index
/* Set bits in INTO corresponding to the variable uids in solution set FROM. */
-static void
+static void
set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
{
unsigned int i;
/* Compute the points-to solution *PT for the variable VI. */
static void
-find_what_var_points_to (varinfo_t vi, struct pt_solution *pt)
+find_what_var_points_to (varinfo_t orig_vi, struct pt_solution *pt)
{
unsigned int i;
bitmap_iterator bi;
bitmap finished_solution;
bitmap result;
+ varinfo_t vi;
memset (pt, 0, sizeof (struct pt_solution));
/* This variable may have been collapsed, let's get the real
variable. */
- vi = get_varinfo (find (vi->id));
+ vi = get_varinfo (find (orig_vi->id));
/* Translate artificial variables into SSA_NAME_PTR_INFO
attributes. */
/* Instead of doing extra work, simply do not create
elaborate points-to information for pt_anything pointers. */
if (pt->anything
- && (vi->is_artificial_var
+ && (orig_vi->is_artificial_var
|| !pt->vars_contains_restrict))
return;
"substitution\n");
init_graph (VEC_length (varinfo_t, varmap) * 2);
-
+
if (dump_file)
fprintf (dump_file, "Building predecessor graph\n");
build_pred_graph ();
-
+
if (dump_file)
fprintf (dump_file, "Detecting pointer and location "
"equivalences\n");
si = perform_var_substitution (graph);
-
+
if (dump_file)
fprintf (dump_file, "Rewriting constraints and unifying "
"variables\n");
static bool
gate_ipa_pta (void)
{
- return (flag_ipa_pta
+ return (optimize
+ && flag_ipa_pta
/* Don't bother doing anything if the program has errors. */
&& !(errorcount || sorrycount));
}
/* Build the constraints. */
for (node = cgraph_nodes; node; node = node->next)
{
- unsigned int varid;
-
/* Nodes without a body are not interesting. Especially do not
visit clones at this point for now - we get duplicate decls
there for inline clones at least. */
if (node->local.externally_visible)
continue;
- varid = create_function_info_for (node->decl,
- cgraph_node_name (node));
+ create_function_info_for (node->decl,
+ cgraph_node_name (node));
}
for (node = cgraph_nodes; node; node = node->next)