void dump_symtab (FILE *f) { symtab_node node; fprintf (f, "Symbol table:\n\n"); FOR_EACH_SYMBOL (node) dump_symtab_node (f, node); }
DEBUG_FUNCTION void verify_symtab_node (symtab_node node) { if (seen_error ()) return; timevar_push (TV_CGRAPH_VERIFY); if (symtab_function_p (node)) verify_cgraph_node (cgraph (node)); else if (verify_symtab_base (node)) { dump_symtab_node (stderr, node); internal_error ("verify_symtab_node failed"); } timevar_pop (TV_CGRAPH_VERIFY); }
DEBUG_FUNCTION void debug_symtab_node (symtab_node node) { dump_symtab_node (stderr, node); }
static void lto_symtab_merge_decls_1 (symtab_node first) { symtab_node e, prevailing; bool diagnosed_p = false; if (cgraph_dump_file) { fprintf (cgraph_dump_file, "Merging nodes for %s. Candidates:\n", symtab_node_asm_name (first)); for (e = first; e; e = e->symbol.next_sharing_asm_name) if (TREE_PUBLIC (e->symbol.decl)) dump_symtab_node (cgraph_dump_file, e); } /* Compute the symbol resolutions. This is a no-op when using the linker plugin and resolution was decided by the linker. */ prevailing = lto_symtab_resolve_symbols (first); /* If there's not a prevailing symbol yet it's an external reference. Happens a lot during ltrans. Choose the first symbol with a cgraph or a varpool node. */ if (!prevailing) { prevailing = first; /* For variables chose with a priority variant with vnode attached (i.e. from unit where external declaration of variable is actually used). When there are multiple variants, chose one with size. This is needed for C++ typeinfos, for example in lto/20081204-1 there are typeifos in both units, just one of them do have size. */ if (TREE_CODE (prevailing->symbol.decl) == VAR_DECL) { for (e = prevailing->symbol.next_sharing_asm_name; e; e = e->symbol.next_sharing_asm_name) if (!COMPLETE_TYPE_P (TREE_TYPE (prevailing->symbol.decl)) && COMPLETE_TYPE_P (TREE_TYPE (e->symbol.decl)) && lto_symtab_symbol_p (e)) prevailing = e; } /* For variables prefer the non-builtin if one is available. */ else if (TREE_CODE (prevailing->symbol.decl) == FUNCTION_DECL) { for (e = first; e; e = e->symbol.next_sharing_asm_name) if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL && !DECL_BUILT_IN (e->symbol.decl) && lto_symtab_symbol_p (e)) { prevailing = e; break; } } } symtab_prevail_in_asm_name_hash (prevailing); /* Diagnose mismatched objects. */ for (e = prevailing->symbol.next_sharing_asm_name; e; e = e->symbol.next_sharing_asm_name) { if (TREE_CODE (prevailing->symbol.decl) == TREE_CODE (e->symbol.decl)) continue; if (!lto_symtab_symbol_p (e)) continue; switch (TREE_CODE (prevailing->symbol.decl)) { case VAR_DECL: gcc_assert (TREE_CODE (e->symbol.decl) == FUNCTION_DECL); error_at (DECL_SOURCE_LOCATION (e->symbol.decl), "variable %qD redeclared as function", prevailing->symbol.decl); break; case FUNCTION_DECL: gcc_assert (TREE_CODE (e->symbol.decl) == VAR_DECL); error_at (DECL_SOURCE_LOCATION (e->symbol.decl), "function %qD redeclared as variable", prevailing->symbol.decl); break; default: gcc_unreachable (); } diagnosed_p = true; } if (diagnosed_p) inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl), "previously declared here"); /* Merge the chain to the single prevailing decl and diagnose mismatches. */ lto_symtab_merge_decls_2 (prevailing, diagnosed_p); if (cgraph_dump_file) { fprintf (cgraph_dump_file, "After resolution:\n"); for (e = prevailing; e; e = e->symbol.next_sharing_asm_name) dump_symtab_node (cgraph_dump_file, e); } }
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; }