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]>
---
 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 313610fbe2c..6d589f59442 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 a81f685654f..017c05750bb 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 d03c41f38e4..54f6110c933 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 8c6ec6f8338..435a0d98a7e 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 3dbfad33ea2..a8b6091848b 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);
-- 
2.43.0

Reply via email to