static bool lto_symtab_symbol_p (symtab_node e) { if (!TREE_PUBLIC (e->symbol.decl) && !DECL_EXTERNAL (e->symbol.decl)) return false; return symtab_real_symbol_p (e); }
void build_type_inheritance_graph (void) { struct cgraph_node *n; FILE *inheritance_dump_file; int flags; if (odr_hash.is_created ()) return; timevar_push (TV_IPA_INHERITANCE); inheritance_dump_file = dump_begin (TDI_inheritance, &flags); odr_hash.create (23); /* We reconstruct the graph starting of types of all methods seen in the the unit. */ FOR_EACH_FUNCTION (n) if (DECL_VIRTUAL_P (n->decl) && symtab_real_symbol_p (n)) get_odr_type (method_class_type (TREE_TYPE (n->decl)), true); if (inheritance_dump_file) { dump_type_inheritance_graph (inheritance_dump_file); dump_end (TDI_inheritance, inheritance_dump_file); } timevar_pop (TV_IPA_INHERITANCE); }
static void maybe_record_node (vec <cgraph_node *> &nodes, tree target, pointer_set_t *inserted, bool *completep) { struct cgraph_node *target_node; enum built_in_function fcode; if (!target /* Those are used to mark impossible scenarios. */ || (fcode = DECL_FUNCTION_CODE (target)) == BUILT_IN_UNREACHABLE || fcode == BUILT_IN_TRAP) return; target_node = cgraph_get_node (target); if (target_node != NULL && (TREE_PUBLIC (target) || target_node->definition) && symtab_real_symbol_p (target_node)) { gcc_assert (!target_node->global.inlined_to); gcc_assert (symtab_real_symbol_p (target_node)); if (!pointer_set_insert (inserted, target)) { pointer_set_insert (cached_polymorphic_call_targets, target_node); nodes.safe_push (target_node); } } else if (completep && !type_in_anonymous_namespace_p (method_class_type (TREE_TYPE (target)))) *completep = true; }
static void maybe_record_node (vec <cgraph_node *> &nodes, tree target, pointer_set_t *inserted) { struct cgraph_node *target_node; enum built_in_function fcode; if (target /* Those are used to mark impossible scenarios. */ && (fcode = DECL_FUNCTION_CODE (target)) != BUILT_IN_UNREACHABLE && fcode != BUILT_IN_TRAP && !pointer_set_insert (inserted, target) && (target_node = cgraph_get_node (target)) != NULL && (TREE_PUBLIC (target) || target_node->symbol.definition) && symtab_real_symbol_p ((symtab_node)target_node)) { pointer_set_insert (cached_polymorphic_call_targets, target_node); nodes.safe_push (target_node); } }
static unsigned int ipa_comdats (void) { pointer_map<tree> map; pointer_map<symtab_node *> comdat_head_map; symtab_node *symbol; bool comdat_group_seen = false; symtab_node *first = (symtab_node *) (void *) 1; tree group; /* Start the dataflow by assigning comdat group to symbols that are in comdat groups already. All other externally visible symbols must stay, we use ERROR_MARK_NODE as bottom for the propagation. */ FOR_EACH_DEFINED_SYMBOL (symbol) if (!symtab_real_symbol_p (symbol)) ; else if ((group = symbol->get_comdat_group ()) != NULL) { *map.insert (symbol) = group; *comdat_head_map.insert (group) = symbol; comdat_group_seen = true; /* Mark the symbol so we won't waste time visiting it for dataflow. */ symbol->aux = (symtab_node *) (void *) 1; } /* See symbols that can not be privatized to comdats; that is externally visible symbols or otherwise used ones. We also do not want to mangle user section names. */ else if (symbol->externally_visible || symbol->force_output || symbol->used_from_other_partition || TREE_THIS_VOLATILE (symbol->decl) || symbol->get_section () || (TREE_CODE (symbol->decl) == FUNCTION_DECL && (DECL_STATIC_CONSTRUCTOR (symbol->decl) || DECL_STATIC_DESTRUCTOR (symbol->decl)))) { *map.insert (symtab_alias_ultimate_target (symbol, NULL)) = error_mark_node; /* Mark the symbol so we won't waste time visiting it for dataflow. */ symbol->aux = (symtab_node *) (void *) 1; } else { /* Enqueue symbol for dataflow. */ symbol->aux = first; first = symbol; } if (!comdat_group_seen) { FOR_EACH_DEFINED_SYMBOL (symbol) symbol->aux = NULL; return 0; } /* The actual dataflow. */ while (first != (void *) 1) { tree group = NULL; tree newgroup, *val; symbol = first; first = (symtab_node *)first->aux; /* Get current lattice value of SYMBOL. */ val = map.contains (symbol); if (val) group = *val; /* If it is bottom, there is nothing to do; do not clear AUX so we won't re-queue the symbol. */ if (group == error_mark_node) continue; newgroup = propagate_comdat_group (symbol, group, map); /* If nothing changed, proceed to next symbol. */ if (newgroup == group) { symbol->aux = NULL; continue; } /* Update lattice value and enqueue all references for re-visiting. */ gcc_assert (newgroup); if (val) *val = newgroup; else *map.insert (symbol) = newgroup; enqueue_references (&first, symbol); /* We may need to revisit the symbol unless it is BOTTOM. */ if (newgroup != error_mark_node) symbol->aux = NULL; } /* Finally assign symbols to the sections. */ FOR_EACH_DEFINED_SYMBOL (symbol) { symbol->aux = NULL; if (!symbol->get_comdat_group () && !symbol->alias && symtab_real_symbol_p (symbol)) { tree group = *map.contains (symbol); if (group == error_mark_node) continue; if (dump_file) { fprintf (dump_file, "Localizing symbol\n"); dump_symtab_node (dump_file, symbol); fprintf (dump_file, "To group: %s\n", IDENTIFIER_POINTER (group)); } symtab_for_node_and_aliases (symbol, set_comdat_group, *comdat_head_map.contains (group), true); } } return 0; }