static void update_call_edge_frequencies (gimple_seq_node first, basic_block bb) { struct cgraph_node *cfun_node = NULL; int bb_freq = 0; gimple_seq_node n; for (n = first; n ; n = n->next) if (is_gimple_call (n)) { struct cgraph_edge *e; /* These function calls are expensive enough that we want to avoid calling them if we never see any calls. */ if (cfun_node == NULL) { cfun_node = cgraph_node::get (current_function_decl); bb_freq = (compute_call_stmt_bb_frequency (current_function_decl, bb)); } e = cfun_node->get_edge (n); if (e != NULL) e->frequency = bb_freq; } }
unsigned int cgraph_edge::rebuild_edges (void) { basic_block bb; cgraph_node *node = cgraph_node::get (current_function_decl); gimple_stmt_iterator gsi; node->remove_callees (); node->remove_all_references (); node->count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; FOR_EACH_BB_FN (bb, cfun) { for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple stmt = gsi_stmt (gsi); tree decl; if (gcall *call_stmt = dyn_cast <gcall *> (stmt)) { int freq = compute_call_stmt_bb_frequency (current_function_decl, bb); decl = gimple_call_fndecl (call_stmt); if (decl) node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count, freq); else if (gimple_call_internal_p (call_stmt)) ; else node->create_indirect_edge (call_stmt, gimple_call_flags (call_stmt), bb->count, freq); } node->record_stmt_references (stmt); } for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) node->record_stmt_references (gsi_stmt (gsi)); } record_eh_tables (node, cfun); gcc_assert (!node->global.inlined_to); if (node->instrumented_version && !node->instrumentation_clone) node->create_reference (node->instrumented_version, IPA_REF_CHKP, NULL); return 0; }
unsigned int rebuild_cgraph_edges (void) { basic_block bb; struct cgraph_node *node = cgraph_get_node (current_function_decl); gimple_stmt_iterator gsi; cgraph_node_remove_callees (node); ipa_remove_all_references (&node->ref_list); node->count = ENTRY_BLOCK_PTR->count; FOR_EACH_BB (bb) { for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple stmt = gsi_stmt (gsi); tree decl; if (is_gimple_call (stmt)) { int freq = compute_call_stmt_bb_frequency (current_function_decl, bb); decl = gimple_call_fndecl (stmt); if (decl) cgraph_create_edge (node, cgraph_get_create_node (decl), stmt, bb->count, freq); else cgraph_create_indirect_edge (node, stmt, gimple_call_flags (stmt), bb->count, freq); } walk_stmt_load_store_addr_ops (stmt, node, mark_load, mark_store, mark_address); } for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi)) walk_stmt_load_store_addr_ops (gsi_stmt (gsi), node, mark_load, mark_store, mark_address); } record_eh_tables (node, cfun); gcc_assert (!node->global.inlined_to); return 0; }
static void stackleak_add_instrumentation(gimple_stmt_iterator *gsi) { gimple stmt; gcall *track_stack; cgraph_node_ptr node; int frequency; basic_block bb; // insert call to void pax_track_stack(void) stmt = gimple_build_call(track_function_decl, 0); track_stack = as_a_gcall(stmt); gsi_insert_after(gsi, track_stack, GSI_CONTINUE_LINKING); // update the cgraph bb = gimple_bb(track_stack); node = cgraph_get_create_node(track_function_decl); gcc_assert(node); frequency = compute_call_stmt_bb_frequency(current_function_decl, bb); cgraph_create_edge(cgraph_get_node(current_function_decl), node, track_stack, bb->count, frequency, bb->loop_depth); }
static void stackleak_check_alloca(gimple_stmt_iterator *gsi) { gimple stmt; gcall *check_alloca; tree alloca_size; cgraph_node_ptr node; int frequency; basic_block bb; // insert call to void pax_check_alloca(unsigned long size) alloca_size = gimple_call_arg(gsi_stmt(*gsi), 0); stmt = gimple_build_call(check_function_decl, 1, alloca_size); check_alloca = as_a_gcall(stmt); gsi_insert_before(gsi, check_alloca, GSI_SAME_STMT); // update the cgraph bb = gimple_bb(check_alloca); node = cgraph_get_create_node(check_function_decl); gcc_assert(node); frequency = compute_call_stmt_bb_frequency(current_function_decl, bb); cgraph_create_edge(cgraph_get_node(current_function_decl), node, check_alloca, bb->count, frequency, bb->loop_depth); }
static unsigned int build_cgraph_edges (void) { basic_block bb; struct cgraph_node *node = cgraph_get_node (current_function_decl); struct pointer_set_t *visited_nodes = pointer_set_create (); gimple_stmt_iterator gsi; tree decl; unsigned ix; /* Create the callgraph edges and record the nodes referenced by the function. body. */ FOR_EACH_BB_FN (bb, cfun) { for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple stmt = gsi_stmt (gsi); tree decl; if (is_gimple_debug (stmt)) continue; if (is_gimple_call (stmt)) { int freq = compute_call_stmt_bb_frequency (current_function_decl, bb); decl = gimple_call_fndecl (stmt); if (decl) cgraph_create_edge (node, cgraph_get_create_node (decl), stmt, bb->count, freq); else if (gimple_call_internal_p (stmt)) ; else cgraph_create_indirect_edge (node, stmt, gimple_call_flags (stmt), bb->count, freq); } ipa_record_stmt_references (node, stmt); if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL && gimple_omp_parallel_child_fn (stmt)) { tree fn = gimple_omp_parallel_child_fn (stmt); ipa_record_reference (node, cgraph_get_create_node (fn), IPA_REF_ADDR, stmt); } if (gimple_code (stmt) == GIMPLE_OMP_TASK) { tree fn = gimple_omp_task_child_fn (stmt); if (fn) ipa_record_reference (node, cgraph_get_create_node (fn), IPA_REF_ADDR, stmt); fn = gimple_omp_task_copy_fn (stmt); if (fn) ipa_record_reference (node, cgraph_get_create_node (fn), IPA_REF_ADDR, stmt); } } for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) ipa_record_stmt_references (node, gsi_stmt (gsi)); } /* Look for initializers of constant variables and private statics. */ FOR_EACH_LOCAL_DECL (cfun, ix, decl) if (TREE_CODE (decl) == VAR_DECL && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) && !DECL_HAS_VALUE_EXPR_P (decl)) varpool_finalize_decl (decl); record_eh_tables (node, cfun); pointer_set_destroy (visited_nodes); return 0; }