/* Return true if list contains an alias. */ bool ipa_ref_has_aliases_p (struct ipa_ref_list *ref_list) { struct ipa_ref *ref; int i; for (i = 0; ipa_ref_list_referring_iterate (ref_list, i, ref); i++) if (ref->use == IPA_REF_ALIAS) return true; return false; }
void ipa_clone_referring (symtab_node dest_node, struct ipa_ref_list *src) { struct ipa_ref *ref; int i; for (i = 0; ipa_ref_list_referring_iterate (src, i, ref); i++) ipa_record_reference (ref->referring, dest_node, ref->use, ref->stmt); }
static void assemble_aliases (varpool_node *node) { int i; struct ipa_ref *ref; for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) if (ref->use == IPA_REF_ALIAS) { varpool_node *alias = ipa_ref_referring_varpool_node (ref); do_assemble_alias (alias->decl, DECL_ASSEMBLER_NAME (node->decl)); assemble_aliases (alias); } }
void ipa_dump_referring (FILE * file, struct ipa_ref_list *list) { struct ipa_ref *ref; int i; for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++) { fprintf (file, "%s/%i (%s)", symtab_node_asm_name (ref->referring), ref->referring->symbol.order, ipa_ref_use_name [ref->use]); } fprintf (file, "\n"); }
void ipa_dump_referring (FILE * file, struct ipa_ref_list *list) { struct ipa_ref *ref; int i; for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++) { fprintf (file, "%s/%i (%s)", ref->referring->asm_name (), ref->referring->order, ipa_ref_use_name [ref->use]); if (ref->speculative) fprintf (file, " (speculative)"); } fprintf (file, "\n"); }
void ipa_clone_referring (symtab_node *dest_node, struct ipa_ref_list *src) { struct ipa_ref *ref, *ref2; int i; for (i = 0; ipa_ref_list_referring_iterate (src, i, ref); i++) { bool speculative = ref->speculative; unsigned int stmt_uid = ref->lto_stmt_uid; ref2 = ipa_record_reference (ref->referring, dest_node, ref->use, ref->stmt); ref2->speculative = speculative; ref2->lto_stmt_uid = stmt_uid; } }
bool varpool_for_node_and_aliases (varpool_node *node, bool (*callback) (varpool_node *, void *), void *data, bool include_overwritable) { int i; struct ipa_ref *ref; if (callback (node, data)) return true; for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) if (ref->use == IPA_REF_ALIAS) { varpool_node *alias = ipa_ref_referring_varpool_node (ref); if (include_overwritable || cgraph_variable_initializer_availability (alias) > AVAIL_OVERWRITABLE) if (varpool_for_node_and_aliases (alias, callback, data, include_overwritable)) return true; } return false; }
bool symtab_for_node_and_aliases (symtab_node node, bool (*callback) (symtab_node, void *), void *data, bool include_overwritable) { int i; struct ipa_ref *ref; if (callback (node, data)) return true; for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++) if (ref->use == IPA_REF_ALIAS) { symtab_node alias = ref->referring; if (include_overwritable || symtab_node_availability (alias) > AVAIL_OVERWRITABLE) if (symtab_for_node_and_aliases (alias, callback, data, include_overwritable)) return true; } return false; }
DEBUG_FUNCTION bool verify_symtab_base (symtab_node *node) { bool error_found = false; symtab_node *hashed_node; if (is_a <cgraph_node> (node)) { if (TREE_CODE (node->decl) != FUNCTION_DECL) { error ("function symbol is not function"); error_found = true; } } else if (is_a <varpool_node> (node)) { if (TREE_CODE (node->decl) != VAR_DECL) { error ("variable symbol is not variable"); error_found = true; } } else { error ("node has unknown type"); error_found = true; } if (cgraph_state != CGRAPH_LTO_STREAMING) { hashed_node = symtab_get_node (node->decl); if (!hashed_node) { error ("node not found in symtab decl hashtable"); error_found = true; } if (hashed_node != node && (!is_a <cgraph_node> (node) || !dyn_cast <cgraph_node> (node)->clone_of || dyn_cast <cgraph_node> (node)->clone_of->decl != node->decl)) { error ("node differs from symtab decl hashtable"); error_found = true; } } if (assembler_name_hash) { hashed_node = symtab_node_for_asm (DECL_ASSEMBLER_NAME (node->decl)); if (hashed_node && hashed_node->previous_sharing_asm_name) { error ("assembler name hash list corrupted"); error_found = true; } while (hashed_node) { if (hashed_node == node) break; hashed_node = hashed_node->next_sharing_asm_name; } if (!hashed_node && !(is_a <varpool_node> (node) || DECL_HARD_REGISTER (node->decl))) { error ("node not found in symtab assembler name hash"); error_found = true; } } if (node->previous_sharing_asm_name && node->previous_sharing_asm_name->next_sharing_asm_name != node) { error ("double linked list of assembler names corrupted"); error_found = true; } if (node->analyzed && !node->definition) { error ("node is analyzed byt it is not a definition"); error_found = true; } if (node->cpp_implicit_alias && !node->alias) { error ("node is alias but not implicit alias"); error_found = true; } if (node->alias && !node->definition && !node->weakref) { error ("node is alias but not definition"); error_found = true; } if (node->weakref && !node->alias) { error ("node is weakref but not an alias"); error_found = true; } if (node->same_comdat_group) { symtab_node *n = node->same_comdat_group; if (!DECL_ONE_ONLY (n->decl)) { error ("non-DECL_ONE_ONLY node in a same_comdat_group list"); error_found = true; } if (n->type != node->type) { error ("mixing different types of symbol in same comdat groups is not supported"); error_found = true; } if (n == node) { error ("node is alone in a comdat group"); error_found = true; } do { if (!n->same_comdat_group) { error ("same_comdat_group is not a circular list"); error_found = true; break; } n = n->same_comdat_group; } while (n != node); if (symtab_comdat_local_p (node)) { struct ipa_ref_list *refs = &node->ref_list; struct ipa_ref *ref; for (int i = 0; ipa_ref_list_referring_iterate (refs, i, ref); ++i) { if (!symtab_in_same_comdat_p (ref->referring, node)) { error ("comdat-local symbol referred to by %s outside its " "comdat", identifier_to_locale (ref->referring->name())); error_found = true; } } } } return error_found; }
tree propagate_comdat_group (struct symtab_node *symbol, tree newgroup, pointer_map <tree> &map) { int i; struct ipa_ref *ref; /* Walk all references to SYMBOL, recursively dive into aliases. */ for (i = 0; ipa_ref_list_referring_iterate (&symbol->ref_list, i, ref) && newgroup != error_mark_node; i++) { struct symtab_node *symbol2 = ref->referring; if (ref->use == IPA_REF_ALIAS) { newgroup = propagate_comdat_group (symbol2, newgroup, map); continue; } /* One COMDAT group can not hold both variables and functions at a same time. For now we just go to BOTTOM, in future we may invent special comdat groups for this case. */ if (symbol->type != symbol2->type) { newgroup = error_mark_node; break; } /* If we see inline clone, its comdat group actually corresponds to the comdat group of the function it is inlined to. */ if (cgraph_node * cn = dyn_cast <cgraph_node *> (symbol2)) { if (cn->global.inlined_to) symbol2 = cn->global.inlined_to; } /* The actual merge operation. */ tree *val2 = map.contains (symbol2); if (val2 && *val2 != newgroup) { if (!newgroup) newgroup = *val2; else newgroup = error_mark_node; } } /* If we analyze function, walk also callers. */ cgraph_node *cnode = dyn_cast <cgraph_node *> (symbol); if (cnode) for (struct cgraph_edge * edge = cnode->callers; edge && newgroup != error_mark_node; edge = edge->next_caller) { struct symtab_node *symbol2 = edge->caller; /* If we see inline clone, its comdat group actually corresponds to the comdat group of the function it is inlined to. */ if (cgraph_node * cn = dyn_cast <cgraph_node *> (symbol2)) { if (cn->global.inlined_to) symbol2 = cn->global.inlined_to; } /* The actual merge operation. */ tree *val2 = map.contains (symbol2); if (val2 && *val2 != newgroup) { if (!newgroup) newgroup = *val2; else newgroup = error_mark_node; } } return newgroup; }