static void
do_compile ()
{
.....
compile_file()
....
}
static void
compile_file (void)
{
...
/* Run the actual compilation process. */
if (!in_lto_p)
{
timevar_start (TV_PHASE_OPT_GEN);
symtab->finalize_compilation_unit ();
timevar_stop (TV_PHASE_OPT_GEN);
}
.....
}
void
symbol_table::finalize_compilation_unit (void)
{
.....
/* Gimplify and lower all functions, compute reachability and
remove unreachable nodes. */
analyze_functions (/*first_time=*/true);
/* Mark alias targets necessary and emit diagnostics. */
handle_alias_pairs ();
/* Gimplify and lower thunks. */
analyze_functions (/*first_time=*/false);
.....
}
static void
analyze_functions (bool first_time)
{
/* Keep track of already processed nodes when called multiple times for
intermodule optimization. */
cgraph_node *first_handled = first_analyzed;
varpool_node *first_handled_var = first_analyzed_var;
hash_set<void *> reachable_call_targets;
symtab_node *node;
symtab_node *next;
int i;
ipa_ref *ref;
bool changed = true;
location_t saved_loc = input_location;
bitmap_obstack_initialize (NULL);
symtab->state = CONSTRUCTION;
input_location = UNKNOWN_LOCATION;
thunk_info::process_early_thunks ();
/* Ugly, but the fixup cannot happen at a time same body alias is created;
C++ FE is confused about the COMDAT groups being right. */
if (symtab->cpp_implicit_aliases_done)
FOR_EACH_SYMBOL (node)
if (node->cpp_implicit_alias)
node->fixup_same_cpp_alias_visibility (node->get_alias_target ());
build_type_inheritance_graph ();
if (flag_openmp && first_time)
omp_discover_implicit_declare_target ();
/* Analysis adds static variables that in turn adds references to new functions.
So we need to iterate the process until it stabilize. */
while (changed)
{
changed = false;
process_function_and_variable_attributes (first_analyzed,
first_analyzed_var);
/* First identify the trivially needed symbols. */
for (node = symtab->first_symbol ();
node != first_analyzed
&& node != first_analyzed_var; node = node->next)
{
/* Convert COMDAT group designators to IDENTIFIER_NODEs. */
node->get_comdat_group_id ();
if (node->needed_p ())
{
enqueue_node (node);
if (!changed && symtab->dump_file)
fprintf (symtab->dump_file, "Trivially needed symbols:");
changed = true;
if (symtab->dump_file)
fprintf (symtab->dump_file, " %s", node->dump_asm_name ());
}
if (node == first_analyzed
|| node == first_analyzed_var)
break;
}
symtab->process_new_functions ();
first_analyzed_var = symtab->first_variable ();
first_analyzed = symtab->first_function ();
if (changed && symtab->dump_file)
fprintf (symtab->dump_file, "\n");
/* Lower representation, build callgraph edges and references for all trivially
needed symbols and all symbols referred by them. */
while (queued_nodes != &symtab_terminator)
{
changed = true;
node = queued_nodes;
queued_nodes = (symtab_node *)queued_nodes->aux;
cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
if (cnode && cnode->definition)
{
cgraph_edge *edge;
tree decl = cnode->decl;
/* ??? It is possible to create extern inline function
and later using weak alias attribute to kill its body.
See gcc.c-torture/compile/20011119-1.c */
if (!DECL_STRUCT_FUNCTION (decl)
&& !cnode->alias
&& !cnode->thunk
&& !cnode->dispatcher_function)
{
cnode->reset ();
cnode->redefined_extern_inline = true;
continue;
}
if (!cnode->analyzed)
cnode->analyze ();
for (edge = cnode->callees; edge; edge = edge->next_callee)
if (edge->callee->definition
&& (!DECL_EXTERNAL (edge->callee->decl)
/* When not optimizing, do not try to analyze extern
inline functions. Doing so is pointless. */
|| opt_for_fn (edge