aboutsummaryrefslogtreecommitdiff
path: root/gcc/cgraphunit.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cgraphunit.c')
-rw-r--r--gcc/cgraphunit.c207
1 files changed, 91 insertions, 116 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 2f83767..81436aa 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -169,15 +169,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
static void cgraph_expand_all_functions (void);
static void cgraph_mark_functions_to_output (void);
static void cgraph_expand_function (struct cgraph_node *);
-static tree record_call_1 (tree *, int *, void *);
+static tree record_reference (tree *, int *, void *);
static void cgraph_mark_local_functions (void);
static void cgraph_analyze_function (struct cgraph_node *node);
-static void cgraph_create_edges (struct cgraph_node *node, tree body);
-/* Records tree nodes seen in cgraph_create_edges. Simply using
+/* Records tree nodes seen in record_reference. Simply using
walk_tree_without_duplicates doesn't guarantee each node is visited
once because it gets a new htab upon each recursive call from
- record_calls_1. */
+ record_reference itself. */
static struct pointer_set_t *visited_nodes;
static FILE *cgraph_dump_file;
@@ -265,7 +264,12 @@ cgraph_varpool_analyze_pending_decls (void)
cgraph_varpool_first_unanalyzed_node = cgraph_varpool_first_unanalyzed_node->next_needed;
if (DECL_INITIAL (decl))
- cgraph_create_edges (NULL, DECL_INITIAL (decl));
+ {
+ visited_nodes = pointer_set_create ();
+ walk_tree (&DECL_INITIAL (decl), record_reference, NULL, visited_nodes);
+ pointer_set_destroy (visited_nodes);
+ visited_nodes = NULL;
+ }
changed = true;
}
timevar_pop (TV_CGRAPH);
@@ -435,9 +439,6 @@ cgraph_finalize_function (tree decl, bool nested)
do_warn_unused_parameter (decl);
}
-/* Used only while constructing the callgraph. */
-static basic_block current_basic_block;
-
void
cgraph_lower_function (struct cgraph_node *node)
{
@@ -449,7 +450,7 @@ cgraph_lower_function (struct cgraph_node *node)
/* Walk tree and record all calls. Called via walk_tree. */
static tree
-record_call_1 (tree *tp, int *walk_subtrees, void *data)
+record_reference (tree *tp, int *walk_subtrees, void *data)
{
tree t = *tp;
@@ -480,29 +481,6 @@ record_call_1 (tree *tp, int *walk_subtrees, void *data)
}
break;
- case CALL_EXPR:
- {
- tree decl = get_callee_fndecl (*tp);
- if (decl && TREE_CODE (decl) == FUNCTION_DECL)
- {
- cgraph_create_edge (data, cgraph_node (decl), *tp,
- current_basic_block->count,
- current_basic_block->loop_depth);
-
- /* When we see a function call, we don't want to look at the
- function reference in the ADDR_EXPR that is hanging from
- the CALL_EXPR we're examining here, because we would
- conclude incorrectly that the function's address could be
- taken by something that is not a function call. So only
- walk the function parameter list, skip the other subtrees. */
-
- walk_tree (&TREE_OPERAND (*tp, 1), record_call_1, data,
- visited_nodes);
- *walk_subtrees = 0;
- }
- break;
- }
-
default:
/* Save some cycles by not walking types and declaration as we
won't find anything useful there anyway. */
@@ -525,97 +503,62 @@ record_call_1 (tree *tp, int *walk_subtrees, void *data)
static void
cgraph_create_edges (struct cgraph_node *node, tree body)
{
- /* The nodes we're interested in are never shared, so walk
- the tree ignoring duplicates. */
+ basic_block bb;
+
+ struct function *this_cfun = DECL_STRUCT_FUNCTION (body);
+ block_stmt_iterator bsi;
+ tree step;
visited_nodes = pointer_set_create ();
- gcc_assert (current_basic_block == NULL);
- if (TREE_CODE (body) == FUNCTION_DECL)
- {
- struct function *this_cfun = DECL_STRUCT_FUNCTION (body);
- block_stmt_iterator bsi;
- tree step;
-
- /* Reach the trees by walking over the CFG, and note the
- enclosing basic-blocks in the call edges. */
- FOR_EACH_BB_FN (current_basic_block, this_cfun)
- for (bsi = bsi_start (current_basic_block); !bsi_end_p (bsi); bsi_next (&bsi))
- walk_tree (bsi_stmt_ptr (bsi), record_call_1, node, visited_nodes);
- current_basic_block = NULL;
-
- /* Walk over any private statics that may take addresses of functions. */
- if (TREE_CODE (DECL_INITIAL (body)) == BLOCK)
- {
- for (step = BLOCK_VARS (DECL_INITIAL (body));
- step;
- step = TREE_CHAIN (step))
- if (DECL_INITIAL (step))
- walk_tree (&DECL_INITIAL (step), record_call_1, node, visited_nodes);
- }
- /* Also look here for private statics. */
- if (DECL_STRUCT_FUNCTION (body))
- for (step = DECL_STRUCT_FUNCTION (body)->unexpanded_var_list;
- step;
- step = TREE_CHAIN (step))
+ /* Reach the trees by walking over the CFG, and note the
+ enclosing basic-blocks in the call edges. */
+ FOR_EACH_BB_FN (bb, this_cfun)
+ for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+ {
+ tree stmt = bsi_stmt (bsi);
+ tree call = get_call_expr_in (stmt);
+ tree decl;
+
+ if (call && (decl = get_callee_fndecl (call)))
{
- tree decl = TREE_VALUE (step);
- if (DECL_INITIAL (decl) && TREE_STATIC (decl))
- walk_tree (&DECL_INITIAL (decl), record_call_1, node, visited_nodes);
+ cgraph_create_edge (node, cgraph_node (decl), stmt,
+ bb->count,
+ bb->loop_depth);
+ walk_tree (&TREE_OPERAND (call, 1),
+ record_reference, node, visited_nodes);
+ if (TREE_CODE (stmt) == MODIFY_EXPR)
+ walk_tree (&TREE_OPERAND (stmt, 0),
+ record_reference, node, visited_nodes);
}
+ else
+ walk_tree (bsi_stmt_ptr (bsi), record_reference, node, visited_nodes);
+ }
+
+ /* Walk over any private statics that may take addresses of functions. */
+ if (TREE_CODE (DECL_INITIAL (body)) == BLOCK)
+ {
+ for (step = BLOCK_VARS (DECL_INITIAL (body));
+ step;
+ step = TREE_CHAIN (step))
+ if (DECL_INITIAL (step))
+ walk_tree (&DECL_INITIAL (step), record_reference, node, visited_nodes);
}
- else
- walk_tree (&body, record_call_1, node, visited_nodes);
+
+ /* Also look here for private statics. */
+ if (DECL_STRUCT_FUNCTION (body))
+ for (step = DECL_STRUCT_FUNCTION (body)->unexpanded_var_list;
+ step;
+ step = TREE_CHAIN (step))
+ {
+ tree decl = TREE_VALUE (step);
+ if (DECL_INITIAL (decl) && TREE_STATIC (decl))
+ walk_tree (&DECL_INITIAL (decl), record_reference, node, visited_nodes);
+ }
pointer_set_destroy (visited_nodes);
visited_nodes = NULL;
}
-static bool error_found;
-
-/* Callback of verify_cgraph_node. Check that all call_exprs have
- cgraph nodes. */
-
-static tree
-verify_cgraph_node_1 (tree *tp, int *walk_subtrees, void *data)
-{
- tree t = *tp;
- tree decl;
-
- if (TREE_CODE (t) == CALL_EXPR && (decl = get_callee_fndecl (t)))
- {
- struct cgraph_edge *e = cgraph_edge (data, t);
- if (e)
- {
- if (e->aux)
- {
- error ("Shared call_expr:");
- debug_tree (t);
- error_found = true;
- }
- if (e->callee->decl != cgraph_node (decl)->decl)
- {
- error ("Edge points to wrong declaration:");
- debug_tree (e->callee->decl);
- fprintf (stderr," Instead of:");
- debug_tree (decl);
- }
- e->aux = (void *)1;
- }
- else
- {
- error ("Missing callgraph edge for call expr:");
- debug_tree (t);
- error_found = true;
- }
- }
-
- /* Save some cycles by not walking types and declaration as we
- won't find anything useful there anyway. */
- if (IS_TYPE_OR_DECL_P (*tp))
- *walk_subtrees = 0;
-
- return NULL_TREE;
-}
/* Verify cgraph nodes of given cgraph node. */
void
@@ -626,9 +569,9 @@ verify_cgraph_node (struct cgraph_node *node)
struct function *this_cfun = DECL_STRUCT_FUNCTION (node->decl);
basic_block this_block;
block_stmt_iterator bsi;
+ bool error_found = false;
timevar_push (TV_CGRAPH_VERIFY);
- error_found = false;
for (e = node->callees; e; e = e->next_callee)
if (e->aux)
{
@@ -694,7 +637,38 @@ verify_cgraph_node (struct cgraph_node *node)
enclosing basic-blocks in the call edges. */
FOR_EACH_BB_FN (this_block, this_cfun)
for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
- walk_tree (bsi_stmt_ptr (bsi), verify_cgraph_node_1, node, visited_nodes);
+ {
+ tree stmt = bsi_stmt (bsi);
+ tree call = get_call_expr_in (stmt);
+ tree decl;
+ if (call && (decl = get_callee_fndecl (call)))
+ {
+ struct cgraph_edge *e = cgraph_edge (node, stmt);
+ if (e)
+ {
+ if (e->aux)
+ {
+ error ("Shared call_stmt:");
+ debug_generic_stmt (stmt);
+ error_found = true;
+ }
+ if (e->callee->decl != cgraph_node (decl)->decl)
+ {
+ error ("Edge points to wrong declaration:");
+ debug_tree (e->callee->decl);
+ fprintf (stderr," Instead of:");
+ debug_tree (decl);
+ }
+ e->aux = (void *)1;
+ }
+ else
+ {
+ error ("Missing callgraph edge for call stmt:");
+ debug_generic_stmt (stmt);
+ error_found = true;
+ }
+ }
+ }
pointer_set_destroy (visited_nodes);
visited_nodes = NULL;
}
@@ -706,9 +680,10 @@ verify_cgraph_node (struct cgraph_node *node)
{
if (!e->aux)
{
- error ("Edge %s->%s has no corresponding call_expr",
+ error ("Edge %s->%s has no corresponding call_stmt",
cgraph_node_name (e->caller),
cgraph_node_name (e->callee));
+ debug_generic_stmt (e->call_stmt);
error_found = true;
}
e->aux = 0;