]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
cgraph: Move next/previous from symtab to toplevel_node [PR122955]
authorAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Wed, 3 Dec 2025 21:46:43 +0000 (13:46 -0800)
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Sat, 13 Dec 2025 00:36:22 +0000 (16:36 -0800)
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 <andrew.pinski@oss.qualcomm.com>
gcc/cgraph.h
gcc/cgraphunit.cc
gcc/lto-streamer-out.cc
gcc/lto/lto-partition.cc
gcc/symtab.cc

index 313610fbe2c6daaebfdf98181fe28812a4db2c38..6d589f59442f9c9b9c32b5dea331e6503bccd1cb 100644 (file)
@@ -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 ())
index a81f685654f833f2adefb00acb30056a310dd62f..017c05750bb58c2dc40f17e7cd49e34834076741 100644 (file)
@@ -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.  */
index d03c41f38e4529658f7883f2a23a65d3d06b590c..54f6110c9336631eea59a77fdbb4994f80dd2746 100644 (file)
@@ -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);
     }
 
index 8c6ec6f8338767986925201af5b8c2e791c9dd2b..435a0d98a7e36c5745c7389b93539c6656e7f951 100644 (file)
@@ -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);
     }
 }
index 3dbfad33ea2f892aa12f31f8c00bf661a4db34ef..a8b6091848bbcc785dc3e260c181b93c02ccfed4 100644 (file)
@@ -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);