+/* List of hooks trigerred on cgraph_edge events. */
+struct cgraph_edge_hook_list {
+ cgraph_edge_hook hook;
+ void *data;
+ struct cgraph_edge_hook_list *next;
+};
+
+/* List of hooks trigerred on cgraph_node events. */
+struct cgraph_node_hook_list {
+ cgraph_node_hook hook;
+ void *data;
+ struct cgraph_node_hook_list *next;
+};
+
+/* List of hooks trigerred on events involving two cgraph_edges. */
+struct cgraph_2edge_hook_list {
+ cgraph_2edge_hook hook;
+ void *data;
+ struct cgraph_2edge_hook_list *next;
+};
+
+/* List of hooks trigerred on events involving two cgraph_nodes. */
+struct cgraph_2node_hook_list {
+ cgraph_2node_hook hook;
+ void *data;
+ struct cgraph_2node_hook_list *next;
+};
+
+/* List of hooks triggered when an edge is removed. */
+struct cgraph_edge_hook_list *first_cgraph_edge_removal_hook;
+/* List of hooks triggered when a node is removed. */
+struct cgraph_node_hook_list *first_cgraph_node_removal_hook;
+/* List of hooks triggered when an edge is duplicated. */
+struct cgraph_2edge_hook_list *first_cgraph_edge_duplicated_hook;
+/* List of hooks triggered when a node is duplicated. */
+struct cgraph_2node_hook_list *first_cgraph_node_duplicated_hook;
+/* List of hooks triggered when an function is inserted. */
+struct cgraph_node_hook_list *first_cgraph_function_insertion_hook;
+
+/* Head of a linked list of unused (freed) call graph nodes.
+ Do not GTY((delete)) this list so UIDs gets reliably recycled. */
+static GTY(()) struct cgraph_node *free_nodes;
+/* Head of a linked list of unused (freed) call graph edges.
+ Do not GTY((delete)) this list so UIDs gets reliably recycled. */
+static GTY(()) struct cgraph_edge *free_edges;
+
+/* Macros to access the next item in the list of free cgraph nodes and
+ edges. */
+#define NEXT_FREE_NODE(NODE) (NODE)->next
+#define NEXT_FREE_EDGE(EDGE) (EDGE)->prev_caller
+
+/* Register HOOK to be called with DATA on each removed edge. */
+struct cgraph_edge_hook_list *
+cgraph_add_edge_removal_hook (cgraph_edge_hook hook, void *data)
+{
+ struct cgraph_edge_hook_list *entry;
+ struct cgraph_edge_hook_list **ptr = &first_cgraph_edge_removal_hook;
+
+ entry = (struct cgraph_edge_hook_list *) xmalloc (sizeof (*entry));
+ entry->hook = hook;
+ entry->data = data;
+ entry->next = NULL;
+ while (*ptr)
+ ptr = &(*ptr)->next;
+ *ptr = entry;
+ return entry;
+}
+
+/* Remove ENTRY from the list of hooks called on removing edges. */
+void
+cgraph_remove_edge_removal_hook (struct cgraph_edge_hook_list *entry)
+{
+ struct cgraph_edge_hook_list **ptr = &first_cgraph_edge_removal_hook;
+
+ while (*ptr != entry)
+ ptr = &(*ptr)->next;
+ *ptr = entry->next;
+ free (entry);
+}
+
+/* Call all edge removal hooks. */
+static void
+cgraph_call_edge_removal_hooks (struct cgraph_edge *e)
+{
+ struct cgraph_edge_hook_list *entry = first_cgraph_edge_removal_hook;
+ while (entry)
+ {
+ entry->hook (e, entry->data);
+ entry = entry->next;
+ }
+}
+
+/* Register HOOK to be called with DATA on each removed node. */
+struct cgraph_node_hook_list *
+cgraph_add_node_removal_hook (cgraph_node_hook hook, void *data)
+{
+ struct cgraph_node_hook_list *entry;
+ struct cgraph_node_hook_list **ptr = &first_cgraph_node_removal_hook;
+
+ entry = (struct cgraph_node_hook_list *) xmalloc (sizeof (*entry));
+ entry->hook = hook;
+ entry->data = data;
+ entry->next = NULL;
+ while (*ptr)
+ ptr = &(*ptr)->next;
+ *ptr = entry;
+ return entry;
+}
+
+/* Remove ENTRY from the list of hooks called on removing nodes. */
+void
+cgraph_remove_node_removal_hook (struct cgraph_node_hook_list *entry)
+{
+ struct cgraph_node_hook_list **ptr = &first_cgraph_node_removal_hook;
+
+ while (*ptr != entry)
+ ptr = &(*ptr)->next;
+ *ptr = entry->next;
+ free (entry);
+}
+
+/* Call all node removal hooks. */
+static void
+cgraph_call_node_removal_hooks (struct cgraph_node *node)
+{
+ struct cgraph_node_hook_list *entry = first_cgraph_node_removal_hook;
+ while (entry)
+ {
+ entry->hook (node, entry->data);
+ entry = entry->next;
+ }
+}
+
+/* Register HOOK to be called with DATA on each inserted node. */
+struct cgraph_node_hook_list *
+cgraph_add_function_insertion_hook (cgraph_node_hook hook, void *data)
+{
+ struct cgraph_node_hook_list *entry;
+ struct cgraph_node_hook_list **ptr = &first_cgraph_function_insertion_hook;
+
+ entry = (struct cgraph_node_hook_list *) xmalloc (sizeof (*entry));
+ entry->hook = hook;
+ entry->data = data;
+ entry->next = NULL;
+ while (*ptr)
+ ptr = &(*ptr)->next;
+ *ptr = entry;
+ return entry;
+}
+
+/* Remove ENTRY from the list of hooks called on inserted nodes. */
+void
+cgraph_remove_function_insertion_hook (struct cgraph_node_hook_list *entry)
+{
+ struct cgraph_node_hook_list **ptr = &first_cgraph_function_insertion_hook;
+
+ while (*ptr != entry)
+ ptr = &(*ptr)->next;
+ *ptr = entry->next;
+ free (entry);
+}
+
+/* Call all node insertion hooks. */
+void
+cgraph_call_function_insertion_hooks (struct cgraph_node *node)
+{
+ struct cgraph_node_hook_list *entry = first_cgraph_function_insertion_hook;
+ while (entry)
+ {
+ entry->hook (node, entry->data);
+ entry = entry->next;
+ }
+}
+
+/* Register HOOK to be called with DATA on each duplicated edge. */
+struct cgraph_2edge_hook_list *
+cgraph_add_edge_duplication_hook (cgraph_2edge_hook hook, void *data)
+{
+ struct cgraph_2edge_hook_list *entry;
+ struct cgraph_2edge_hook_list **ptr = &first_cgraph_edge_duplicated_hook;
+
+ entry = (struct cgraph_2edge_hook_list *) xmalloc (sizeof (*entry));
+ entry->hook = hook;
+ entry->data = data;
+ entry->next = NULL;
+ while (*ptr)
+ ptr = &(*ptr)->next;
+ *ptr = entry;
+ return entry;
+}
+
+/* Remove ENTRY from the list of hooks called on duplicating edges. */
+void
+cgraph_remove_edge_duplication_hook (struct cgraph_2edge_hook_list *entry)
+{
+ struct cgraph_2edge_hook_list **ptr = &first_cgraph_edge_duplicated_hook;
+
+ while (*ptr != entry)
+ ptr = &(*ptr)->next;
+ *ptr = entry->next;
+ free (entry);
+}
+
+/* Call all edge duplication hooks. */
+static void
+cgraph_call_edge_duplication_hooks (struct cgraph_edge *cs1,
+ struct cgraph_edge *cs2)
+{
+ struct cgraph_2edge_hook_list *entry = first_cgraph_edge_duplicated_hook;
+ while (entry)
+ {
+ entry->hook (cs1, cs2, entry->data);
+ entry = entry->next;
+ }
+}
+
+/* Register HOOK to be called with DATA on each duplicated node. */
+struct cgraph_2node_hook_list *
+cgraph_add_node_duplication_hook (cgraph_2node_hook hook, void *data)
+{
+ struct cgraph_2node_hook_list *entry;
+ struct cgraph_2node_hook_list **ptr = &first_cgraph_node_duplicated_hook;
+
+ entry = (struct cgraph_2node_hook_list *) xmalloc (sizeof (*entry));
+ entry->hook = hook;
+ entry->data = data;
+ entry->next = NULL;
+ while (*ptr)
+ ptr = &(*ptr)->next;
+ *ptr = entry;
+ return entry;
+}
+
+/* Remove ENTRY from the list of hooks called on duplicating nodes. */
+void
+cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *entry)
+{
+ struct cgraph_2node_hook_list **ptr = &first_cgraph_node_duplicated_hook;
+
+ while (*ptr != entry)
+ ptr = &(*ptr)->next;
+ *ptr = entry->next;
+ free (entry);
+}
+
+/* Call all node duplication hooks. */
+static void
+cgraph_call_node_duplication_hooks (struct cgraph_node *node1,
+ struct cgraph_node *node2)
+{
+ struct cgraph_2node_hook_list *entry = first_cgraph_node_duplicated_hook;
+ while (entry)
+ {
+ entry->hook (node1, node2, entry->data);
+ entry = entry->next;
+ }
+}