https://gcc.gnu.org/g:e9c12ffd710484751428fc301a272e16f641cd56
commit r16-6077-ge9c12ffd710484751428fc301a272e16f641cd56 Author: Andrew Pinski <[email protected]> Date: Wed Dec 3 13:46:43 2025 -0800 cgraph: Move next/previous from symtab to toplevel_node [PR122955] Currently the GC marker functions don't support chain_next on non-toplevel tag structures (and does not error out either). So since r16-4747-g529c25ed6e0a06 if there are a lot of chained symtab_nodes (happens most likely with LTO), the GC marker function could cause a stack overflow because of the recusive nature of the marker. This fixes the problem by moving next/previous to toplevel_node. I had originally thought about doing chain_next/chain_prev and using is_a<symtab_node *> to get if it was symtab_node and then used the next/previous from there. But it was noticed that asm_node had a next too (though not using chain_next) so adding a previous is not going to much more space anyways; there will not be many toplevel inline-asm anyways. Bootstraped and tested on x86_64-linux-gnu. PR ipa/122955 gcc/ChangeLog: * cgraph.h (toplevel_node): Add next and previous fields. Add chain_next and chain_prev to GTY. (symtab_node): Remove next and previous field. Remove chain_next and chain_prev from the GTY. (asm_node): Remove next field. (symtab_node::next_defined_symbol): Use save_as_a<symtab_node*> around next. (symbol_table::unregister): Likewise (FOR_EACH_SYMBOL): Likewise (symbol_table::first_defined_symbol): Likewise (symbol_table::first_variable): Likewise (symbol_table::next_variable): Likewise (symbol_table::first_static_initializer): Likewise (symbol_table::next_static_initializer): Likewise (symbol_table::first_defined_variable): Likewise (symbol_table::next_defined_variable): Likewise (symbol_table::first_defined_function): Likewise (symbol_table::next_defined_function): Likewise (symbol_table::first_function): Likewise (symbol_table::next_function): Likewise (symbol_table::first_function_with_gimple_body): Likewise (symbol_table::next_function_with_gimple_body): Likewise * cgraphunit.cc (analyze_functions): Likewise (output_in_order): Likewise * lto-streamer-out.cc (lto_output): Use save_as_a<asm_node*> around next. * symtab.cc (symtab_node::verify_symtab_nodes): Likewise. gcc/lto/ChangeLog: * lto-partition.cc (lto_1_to_1_map): Use save_as_a<asm_node*> around next. (create_asm_partition): Likewise. Signed-off-by: Andrew Pinski <[email protected]> Diff: --- gcc/cgraph.h | 67 ++++++++++++++++++++++++------------------------ gcc/cgraphunit.cc | 11 ++++---- gcc/lto-streamer-out.cc | 4 ++- gcc/lto/lto-partition.cc | 4 +-- gcc/symtab.cc | 4 ++- 5 files changed, 48 insertions(+), 42 deletions(-) diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 313610fbe2c6..6d589f59442f 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -107,7 +107,9 @@ enum symbol_partitioning_class /* Base of all toplevel entries. Inherited by symtab_node and asm_node. */ -struct GTY ((desc ("%h.type"), tag ("TOPLEVEL_BASE"))) toplevel_node { +struct GTY ((desc ("%h.type"), tag ("TOPLEVEL_BASE"), + chain_next("%h.next"), + chain_prev("%h.previous"))) toplevel_node { /* Constructor. */ explicit toplevel_node (toplevel_type t) : lto_file_data (NULL), order (-1), type (t) @@ -116,6 +118,10 @@ struct GTY ((desc ("%h.type"), tag ("TOPLEVEL_BASE"))) toplevel_node { /* File stream where this node is being written to. */ struct lto_file_decl_data * lto_file_data; + /* Linked list of toplevel entries. */ + toplevel_node *next = nullptr; + toplevel_node *previous = nullptr; + /* Ordering of all cgraph nodes. */ int order; @@ -125,8 +131,7 @@ struct GTY ((desc ("%h.type"), tag ("TOPLEVEL_BASE"))) toplevel_node { /* Base of all entries in the symbol table. The symtab_node is inherited by cgraph and varpol nodes. */ -struct GTY ((tag ("SYMTAB_SYMBOL"), - chain_next ("%h.next"), chain_prev ("%h.previous"))) +struct GTY ((tag ("SYMTAB_SYMBOL"))) symtab_node: public toplevel_node { public: @@ -633,10 +638,6 @@ public: /* Declaration representing the symbol. */ tree decl; - /* Linked list of symbol table entries starting with symtab_nodes. */ - symtab_node *next; - symtab_node *previous; - /* Linked list of symbols with the same asm name. There may be multiple entries for single symbol name during LTO, because symbols are renamed only after partitioning. @@ -2243,10 +2244,8 @@ private: struct GTY ((tag ("TOPLEVEL_ASM"))) asm_node: public toplevel_node { explicit asm_node (tree asm_str) - : toplevel_node (TOPLEVEL_ASM), next (NULL), asm_str (asm_str) + : toplevel_node (TOPLEVEL_ASM), asm_str (asm_str) {} - /* Next asm node. */ - asm_node *next; /* String for this asm node. */ tree asm_str; }; @@ -2867,9 +2866,9 @@ symtab_node::get_alias_target_tree () inline symtab_node * symtab_node::next_defined_symbol (void) { - symtab_node *node1 = next; + symtab_node *node1 = safe_as_a<symtab_node *>(next); - for (; node1; node1 = node1->next) + for (; node1; node1 = safe_as_a<symtab_node *>(node1->next)) if (node1->definition) return node1; @@ -2997,7 +2996,7 @@ symbol_table::unregister (symtab_node *node) if (node->previous) node->previous->next = node->next; else - nodes = node->next; + nodes = safe_as_a<symtab_node *>(node->next); if (node->next) node->next->previous = node->previous; @@ -3026,7 +3025,8 @@ symbol_table::first_symbol (void) /* Walk all symbols. */ #define FOR_EACH_SYMBOL(node) \ - for ((node) = symtab->first_symbol (); (node); (node) = (node)->next) + for ((node) = symtab->first_symbol (); (node); \ + (node) = safe_as_a<symtab_node *>((node)->next)) /* Return first static symbol with definition. */ inline symtab_node * @@ -3034,7 +3034,8 @@ symbol_table::first_defined_symbol (void) { symtab_node *node; - for (node = nodes; node; node = node->next) + for (node = nodes; node; + node = safe_as_a<symtab_node *>(node->next)) if (node->definition) return node; @@ -3051,7 +3052,7 @@ inline varpool_node * symbol_table::first_variable (void) { symtab_node *node; - for (node = nodes; node; node = node->next) + for (node = nodes; node; node = safe_as_a<symtab_node *>(node->next)) if (varpool_node *vnode = dyn_cast <varpool_node *> (node)) return vnode; return NULL; @@ -3061,8 +3062,8 @@ symbol_table::first_variable (void) inline varpool_node * symbol_table::next_variable (varpool_node *node) { - symtab_node *node1 = node->next; - for (; node1; node1 = node1->next) + symtab_node *node1 = safe_as_a<symtab_node *>(node->next); + for (; node1; node1 = safe_as_a<symtab_node *>(node1->next)) if (varpool_node *vnode1 = dyn_cast <varpool_node *> (node1)) return vnode1; return NULL; @@ -3078,7 +3079,7 @@ inline varpool_node * symbol_table::first_static_initializer (void) { symtab_node *node; - for (node = nodes; node; node = node->next) + for (node = nodes; node; node = safe_as_a<symtab_node *>(node->next)) { varpool_node *vnode = dyn_cast <varpool_node *> (node); if (vnode && DECL_INITIAL (node->decl)) @@ -3091,8 +3092,8 @@ symbol_table::first_static_initializer (void) inline varpool_node * symbol_table::next_static_initializer (varpool_node *node) { - symtab_node *node1 = node->next; - for (; node1; node1 = node1->next) + symtab_node *node1 = safe_as_a<symtab_node *>(node->next); + for (; node1; node1 = safe_as_a<symtab_node *>(node1->next)) { varpool_node *vnode1 = dyn_cast <varpool_node *> (node1); if (vnode1 && DECL_INITIAL (node1->decl)) @@ -3111,7 +3112,7 @@ inline varpool_node * symbol_table::first_defined_variable (void) { symtab_node *node; - for (node = nodes; node; node = node->next) + for (node = nodes; node; node = safe_as_a<symtab_node *>(node->next)) { varpool_node *vnode = dyn_cast <varpool_node *> (node); if (vnode && vnode->definition) @@ -3124,8 +3125,8 @@ symbol_table::first_defined_variable (void) inline varpool_node * symbol_table::next_defined_variable (varpool_node *node) { - symtab_node *node1 = node->next; - for (; node1; node1 = node1->next) + symtab_node *node1 = safe_as_a<symtab_node *>(node->next); + for (; node1; node1 = safe_as_a<symtab_node *>(node1->next)) { varpool_node *vnode1 = dyn_cast <varpool_node *> (node1); if (vnode1 && vnode1->definition) @@ -3143,7 +3144,7 @@ inline cgraph_node * symbol_table::first_defined_function (void) { symtab_node *node; - for (node = nodes; node; node = node->next) + for (node = nodes; node; node = safe_as_a<symtab_node *>(node->next)) { cgraph_node *cn = dyn_cast <cgraph_node *> (node); if (cn && cn->definition) @@ -3156,8 +3157,8 @@ symbol_table::first_defined_function (void) inline cgraph_node * symbol_table::next_defined_function (cgraph_node *node) { - symtab_node *node1 = node->next; - for (; node1; node1 = node1->next) + symtab_node *node1 = safe_as_a<symtab_node *>(node->next); + for (; node1; node1 = safe_as_a<symtab_node *>(node1->next)) { cgraph_node *cn1 = dyn_cast <cgraph_node *> (node1); if (cn1 && cn1->definition) @@ -3176,7 +3177,7 @@ inline cgraph_node * symbol_table::first_function (void) { symtab_node *node; - for (node = nodes; node; node = node->next) + for (node = nodes; node; node = safe_as_a<symtab_node *>(node->next)) if (cgraph_node *cn = dyn_cast <cgraph_node *> (node)) return cn; return NULL; @@ -3186,8 +3187,8 @@ symbol_table::first_function (void) inline cgraph_node * symbol_table::next_function (cgraph_node *node) { - symtab_node *node1 = node->next; - for (; node1; node1 = node1->next) + symtab_node *node1 = safe_as_a<symtab_node *>(node->next); + for (; node1; node1 = safe_as_a<symtab_node *>(node1->next)) if (cgraph_node *cn1 = dyn_cast <cgraph_node *> (node1)) return cn1; return NULL; @@ -3198,7 +3199,7 @@ inline cgraph_node * symbol_table::first_function_with_gimple_body (void) { symtab_node *node; - for (node = nodes; node; node = node->next) + for (node = nodes; node; node = safe_as_a<symtab_node *>(node->next)) { cgraph_node *cn = dyn_cast <cgraph_node *> (node); if (cn && cn->has_gimple_body_p ()) @@ -3211,8 +3212,8 @@ symbol_table::first_function_with_gimple_body (void) inline cgraph_node * symbol_table::next_function_with_gimple_body (cgraph_node *node) { - symtab_node *node1 = node->next; - for (; node1; node1 = node1->next) + symtab_node *node1 = safe_as_a<symtab_node *>(node->next); + for (; node1; node1 = safe_as_a<symtab_node *>(node1->next)) { cgraph_node *cn1 = dyn_cast <cgraph_node *> (node1); if (cn1 && cn1->has_gimple_body_p ()) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index a81f685654f8..017c05750bb5 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -1210,8 +1210,8 @@ analyze_functions (bool first_time) /* First identify the trivially needed symbols. */ for (node = symtab->first_symbol (); - node != first_analyzed - && node != first_analyzed_var; node = node->next) + node != first_analyzed && node != first_analyzed_var; + node = safe_as_a<symtab_node *>(node->next)) { /* Convert COMDAT group designators to IDENTIFIER_NODEs. */ node->get_comdat_group_id (); @@ -1373,7 +1373,7 @@ analyze_functions (bool first_time) node != first_handled && node != first_handled_var; node = next) { - next = node->next; + next = safe_as_a<symtab_node *>(node->next); /* For symbols declared locally we clear TREE_READONLY when emitting the constructor (if one is needed). For external declarations we can not safely assume that the type is readonly because we may be called @@ -1428,7 +1428,7 @@ analyze_functions (bool first_time) } node->aux = NULL; } - for (;node; node = node->next) + for (;node; node = safe_as_a<symtab_node *>(node->next)) node->aux = NULL; first_analyzed = symtab->first_function (); first_analyzed_var = symtab->first_variable (); @@ -2203,7 +2203,8 @@ output_in_order (void) && !DECL_HAS_VALUE_EXPR_P (vnode->decl)) nodes.safe_push (cgraph_order_sort (vnode)); - for (anode = symtab->first_asm_symbol (); anode; anode = anode->next) + for (anode = symtab->first_asm_symbol (); anode; + anode = safe_as_a<asm_node*>(anode->next)) nodes.safe_push (cgraph_order_sort (anode)); /* Sort nodes by order. */ diff --git a/gcc/lto-streamer-out.cc b/gcc/lto-streamer-out.cc index d03c41f38e45..54f6110c9336 100644 --- a/gcc/lto-streamer-out.cc +++ b/gcc/lto-streamer-out.cc @@ -2828,7 +2828,9 @@ lto_output (void) if (!flag_wpa) { asm_node *anode; - for (anode = symtab->first_asm_symbol (); anode; anode = anode->next) + for (anode = symtab->first_asm_symbol (); + anode; + anode = safe_as_a<asm_node*>(anode->next)) lto_set_symtab_encoder_in_partition (encoder, anode); } diff --git a/gcc/lto/lto-partition.cc b/gcc/lto/lto-partition.cc index 8c6ec6f83387..435a0d98a7e3 100644 --- a/gcc/lto/lto-partition.cc +++ b/gcc/lto/lto-partition.cc @@ -383,7 +383,7 @@ lto_1_to_1_map (void) } struct asm_node *anode; - for (anode = symtab->first_asm_symbol (); anode; anode = anode->next) + for (anode = symtab->first_asm_symbol (); anode; anode = safe_as_a<asm_node*>(anode->next)) node_into_file_partition (anode, pmap); create_partition_if_empty (); @@ -406,7 +406,7 @@ create_asm_partition (void) if (anode) { ltrans_partition partition = new_partition ("asm_nodes"); - for (; anode; anode = anode->next) + for (; anode; anode = safe_as_a<asm_node*>(anode->next)) add_symbol_to_partition (partition, anode); } } diff --git a/gcc/symtab.cc b/gcc/symtab.cc index 3dbfad33ea2f..a8b6091848bb 100644 --- a/gcc/symtab.cc +++ b/gcc/symtab.cc @@ -1485,7 +1485,9 @@ symtab_node::verify_symtab_nodes (void) hash_map<tree, symtab_node *> comdat_head_map (251); asm_node *anode; - for (anode = symtab->first_asm_symbol (); anode; anode = anode->next) + for (anode = symtab->first_asm_symbol (); + anode; + anode = safe_as_a<asm_node*>(anode->next)) if (anode->order < 0 || anode->order >= symtab->order) { error ("invalid order in asm node %i", anode->order);
