void cgraph_mark_if_needed (tree decl) { struct cgraph_node *node = cgraph_node (decl); if (node->local.finalized && decide_is_function_needed (node, decl)) cgraph_mark_needed_node (node); }
static void lto_cgraph_replace_node (struct cgraph_node *node, struct cgraph_node *prevailing_node) { struct cgraph_edge *e, *next; bool compatible_p; if (cgraph_dump_file) { fprintf (cgraph_dump_file, "Replacing cgraph node %s/%i by %s/%i" " for symbol %s\n", xstrdup (cgraph_node_name (node)), node->uid, xstrdup (cgraph_node_name (prevailing_node)), prevailing_node->uid, IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name) (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl))))); } /* Merge node flags. */ if (node->needed) cgraph_mark_needed_node (prevailing_node); if (node->reachable) cgraph_mark_reachable_node (prevailing_node); if (node->address_taken) { gcc_assert (!prevailing_node->global.inlined_to); cgraph_mark_address_taken_node (prevailing_node); } /* Redirect all incoming edges. */ compatible_p = types_compatible_p (TREE_TYPE (TREE_TYPE (prevailing_node->decl)), TREE_TYPE (TREE_TYPE (node->decl))); for (e = node->callers; e; e = next) { next = e->next_caller; cgraph_redirect_edge_callee (e, prevailing_node); /* If there is a mismatch between the supposed callee return type and the real one do not attempt to inline this function. ??? We really need a way to match function signatures for ABI compatibility and perform related promotions at inlining time. */ if (!compatible_p) e->call_stmt_cannot_inline_p = 1; } /* Redirect incomming references. */ ipa_clone_refering (prevailing_node, NULL, &node->ref_list); /* Finally remove the replaced node. */ cgraph_remove_node (node); }
static tree build_junk_fn(unsigned id) { char fnname[32] = {0}; tree decl, resdecl, initial, proto; /* Func decl */ snprintf(fnname, 31, "__func%d", id); proto = build_varargs_function_type_list(void_type_node, NULL_TREE); decl = build_fn_decl(fnname, proto); SET_DECL_ASSEMBLER_NAME(decl, get_identifier(fnname)); printf(TAG "Creating junk function: %s\n", fnname); /* Result */ resdecl=build_decl(BUILTINS_LOCATION,RESULT_DECL,NULL_TREE,void_type_node); DECL_ARTIFICIAL(resdecl) = 1; DECL_CONTEXT(resdecl) = decl; DECL_RESULT(decl) = resdecl; /* Initial */ initial = make_node(BLOCK); TREE_USED(initial) = 1; DECL_INITIAL(decl) = initial; DECL_UNINLINABLE(decl) = 1; DECL_EXTERNAL(decl) = 0; DECL_PRESERVE_P(decl) = 1; /* Func decl */ TREE_USED(decl) = 1; TREE_PUBLIC(decl) = 1; TREE_STATIC(decl) = 1; DECL_ARTIFICIAL(decl) = 1; /* Make the function */ push_struct_function(decl); /* DECL_SAVED_TREE(decl) = gen_junk(); */ cfun->function_end_locus = BUILTINS_LOCATION; gimplify_function_tree(decl); /* Update */ cgraph_add_new_function(decl, false); cgraph_mark_needed_node(cgraph_node(decl)); current_function_decl = NULL_TREE; pop_cfun(); return decl; }
void cgraph_finalize_function (tree decl, bool nested) { struct cgraph_node *node = cgraph_node (decl); if (node->local.finalized) cgraph_reset_node (node); node->pid = cgraph_max_pid ++; notice_global_symbol (decl); node->local.finalized = true; node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL; record_cdtor_fn (node->decl); if (node->nested) lower_nested_functions (decl); gcc_assert (!node->nested); if (decide_is_function_needed (node, decl)) cgraph_mark_needed_node (node); /* Since we reclaim unreachable nodes at the end of every language level unit, we need to be conservative about possible entry points there. */ if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))) cgraph_mark_reachable_node (node); /* If we've not yet emitted decl, tell the debug info about it. */ if (!TREE_ASM_WRITTEN (decl)) (*debug_hooks->deferred_inline_function) (decl); /* Possibly warn about unused parameters. */ if (warn_unused_parameter) do_warn_unused_parameter (decl); if (!nested) ggc_collect (); }