/* Callgraph construction.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Jan Hubicka
/* Mark address taken in STMT. */
static bool
-mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
- void *data ATTRIBUTE_UNUSED)
+mark_address (gimple stmt, tree addr, void *data)
{
+ addr = get_base_address (addr);
if (TREE_CODE (addr) == FUNCTION_DECL)
{
struct cgraph_node *node = cgraph_node (addr);
node, NULL,
IPA_REF_ADDR, stmt);
}
- else
+ else if (addr && TREE_CODE (addr) == VAR_DECL
+ && (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
{
- addr = get_base_address (addr);
- if (addr && TREE_CODE (addr) == VAR_DECL
- && (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
- {
- struct varpool_node *vnode = varpool_node (addr);
- int walk_subtrees;
+ struct varpool_node *vnode = varpool_node (addr);
+ int walk_subtrees;
- if (lang_hooks.callgraph.analyze_expr)
- lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees);
- varpool_mark_needed_node (vnode);
- if (vnode->alias && vnode->extra_name)
- vnode = vnode->extra_name;
- ipa_record_reference ((struct cgraph_node *)data, NULL,
- NULL, vnode,
- IPA_REF_ADDR, stmt);
- }
+ if (lang_hooks.callgraph.analyze_expr)
+ lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees);
+ varpool_mark_needed_node (vnode);
+ if (vnode->alias && vnode->extra_name)
+ vnode = vnode->extra_name;
+ ipa_record_reference ((struct cgraph_node *)data, NULL,
+ NULL, vnode,
+ IPA_REF_ADDR, stmt);
}
return false;
/* Mark load of T. */
static bool
-mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t,
- void *data ATTRIBUTE_UNUSED)
+mark_load (gimple stmt, tree t, void *data)
{
t = get_base_address (t);
- if (t && TREE_CODE (t) == VAR_DECL
- && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
+ if (t && TREE_CODE (t) == FUNCTION_DECL)
+ {
+ /* ??? This can happen on platforms with descriptors when these are
+ directly manipulated in the code. Pretend that it's an address. */
+ struct cgraph_node *node = cgraph_node (t);
+ cgraph_mark_address_taken_node (node);
+ ipa_record_reference ((struct cgraph_node *)data, NULL,
+ node, NULL,
+ IPA_REF_ADDR, stmt);
+ }
+ else if (t && TREE_CODE (t) == VAR_DECL
+ && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
{
struct varpool_node *vnode = varpool_node (t);
int walk_subtrees;
/* Mark store of T. */
static bool
-mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t,
- void *data ATTRIBUTE_UNUSED)
+mark_store (gimple stmt, tree t, void *data)
{
t = get_base_address (t);
if (t && TREE_CODE (t) == VAR_DECL
vnode = vnode->extra_name;
ipa_record_reference ((struct cgraph_node *)data, NULL,
NULL, vnode,
- IPA_REF_STORE, NULL);
+ IPA_REF_STORE, stmt);
}
return false;
}
struct cgraph_node *node = cgraph_node (current_function_decl);
struct pointer_set_t *visited_nodes = pointer_set_create ();
gimple_stmt_iterator gsi;
- tree step;
+ tree decl;
+ unsigned ix;
/* Create the callgraph edges and record the nodes referenced by the function.
body. */
&& gimple_omp_parallel_child_fn (stmt))
{
tree fn = gimple_omp_parallel_child_fn (stmt);
- cgraph_mark_needed_node (cgraph_node (fn));
+ ipa_record_reference (node, NULL, cgraph_node (fn),
+ NULL, IPA_REF_ADDR, stmt);
}
if (gimple_code (stmt) == GIMPLE_OMP_TASK)
{
tree fn = gimple_omp_task_child_fn (stmt);
if (fn)
- cgraph_mark_needed_node (cgraph_node (fn));
+ ipa_record_reference (node, NULL, cgraph_node (fn),
+ NULL, IPA_REF_ADDR, stmt);
fn = gimple_omp_task_copy_fn (stmt);
if (fn)
- cgraph_mark_needed_node (cgraph_node (fn));
+ ipa_record_reference (node, NULL, cgraph_node (fn),
+ NULL, IPA_REF_ADDR, stmt);
}
}
for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
}
/* Look for initializers of constant variables and private statics. */
- for (step = cfun->local_decls;
- step;
- step = TREE_CHAIN (step))
- {
- tree decl = TREE_VALUE (step);
- if (TREE_CODE (decl) == VAR_DECL
- && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl)))
- varpool_finalize_decl (decl);
- }
+ FOR_EACH_LOCAL_DECL (cfun, ix, decl)
+ if (TREE_CODE (decl) == VAR_DECL
+ && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl)))
+ varpool_finalize_decl (decl);
record_eh_tables (node, cfun);
pointer_set_destroy (visited_nodes);
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- TV_NONE, /* tv_id */
+ TV_CGRAPH, /* tv_id */
PROP_cfg, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */