Hi,
this patch fixes ARM LTO failures caused by my ctor offlining patch.
The problem is that error_mark_node used to mark offlined ctors is also
used specially thorough varasm.c mostly as an altenrative to "no constructor".
I am not quite sure this code is needed anyway as we don't output variables
in programs with error, but bellow is safe fix that disables this path
for LTO.

It also makes get_variable_section to stream in the constructor so local
flags are computed correctly.

Bootstrapped/regtested x86_64-linux and tested to fix ARM failures.

Comitted.
Honza

        PR lto/61802
        * varasm.c (bss_initializer_p): Handle offlined ctors.
        (align_variable, get_variable_align): Likewise.
        (make_decl_one_only): Likewise.
        (default_binds_local_p_1): Likewise.
        (decl_binds_to_current_def_p): Likewise.
        (get_variable_section): Get constructor if it is offlined.
        (assemble_variable_contents): Sanity check that the caller
        streamed in the ctor in LTO.
Index: varasm.c
===================================================================
--- varasm.c    (revision 212984)
+++ varasm.c    (working copy)
@@ -956,7 +956,10 @@ bool
 bss_initializer_p (const_tree decl)
 {
   return (DECL_INITIAL (decl) == NULL
-         || DECL_INITIAL (decl) == error_mark_node
+         /* In LTO we have no errors in program; error_mark_node is used
+            to mark offlined constructors.  */
+         || (DECL_INITIAL (decl) == error_mark_node
+             && !in_lto_p)
          || (flag_zero_initialized_in_bss
              /* Leave constant zeroes in .rodata so they
                 can be shared.  */
@@ -1017,7 +1020,9 @@ align_variable (tree decl, bool dont_out
 #endif
 #ifdef CONSTANT_ALIGNMENT
          if (DECL_INITIAL (decl) != 0
-             && DECL_INITIAL (decl) != error_mark_node)
+             /* In LTO we have no errors in program; error_mark_node is used
+                to mark offlined constructors.  */
+             && (in_lto_p || DECL_INITIAL (decl) != error_mark_node))
            {
              unsigned int const_align
                = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align);
@@ -1068,7 +1073,10 @@ get_variable_align (tree decl)
        align = data_align;
 #endif
 #ifdef CONSTANT_ALIGNMENT
-      if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node)
+      if (DECL_INITIAL (decl) != 0
+         /* In LTO we have no errors in program; error_mark_node is used
+            to mark offlined constructors.  */
+         && (in_lto_p || DECL_INITIAL (decl) != error_mark_node))
        {
          unsigned int const_align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl),
                                                         align);
@@ -1092,13 +1100,20 @@ get_variable_section (tree decl, bool pr
 {
   addr_space_t as = ADDR_SPACE_GENERIC;
   int reloc;
-  symtab_node *snode = symtab_node::get (decl);
-  if (snode)
-    decl = snode->ultimate_alias_target ()->decl;
+  varpool_node *vnode = varpool_node::get (decl);
+  if (vnode)
+    {
+      vnode = vnode->ultimate_alias_target ();
+      decl = vnode->decl;
+    }
 
   if (TREE_TYPE (decl) != error_mark_node)
     as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
 
+  /* We need the constructor to figure out reloc flag.  */
+  if (vnode)
+    vnode->get_constructor ();
+
   if (DECL_COMMON (decl))
     {
       /* If the decl has been given an explicit section name, or it resides
@@ -1963,6 +1978,9 @@ assemble_variable_contents (tree decl, c
 
   if (!dont_output_data)
     {
+      /* Caller is supposed to use varpool_get_constructor when it wants
+        to output the body.  */
+      gcc_assert (!in_lto_p || DECL_INITIAL (decl) != error_mark_node);
       if (DECL_INITIAL (decl)
          && DECL_INITIAL (decl) != error_mark_node
          && !initializer_zerop (DECL_INITIAL (decl)))
@@ -5890,7 +5908,8 @@ make_decl_one_only (tree decl, tree comd
       symbol->set_comdat_group (comdat_group);
     }
   else if (TREE_CODE (decl) == VAR_DECL
-      && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
+           && (DECL_INITIAL (decl) == 0
+              || (!in_lto_p && DECL_INITIAL (decl) == error_mark_node)))
     DECL_COMMON (decl) = 1;
   else
     {
@@ -6752,7 +6771,7 @@ default_binds_local_p_1 (const_tree exp,
   else if (DECL_COMMON (exp)
           && !resolved_locally
           && (DECL_INITIAL (exp) == NULL
-              || DECL_INITIAL (exp) == error_mark_node))
+              || (!in_lto_p && DECL_INITIAL (exp) == error_mark_node)))
     local_p = false;
   /* Otherwise we're left with initialized (or non-common) global data
      which is of necessity defined locally.  */
@@ -6807,7 +6826,7 @@ decl_binds_to_current_def_p (const_tree
     return false;
   if (DECL_COMMON (decl)
       && (DECL_INITIAL (decl) == NULL
-         || DECL_INITIAL (decl) == error_mark_node))
+         || (!in_lto_p && DECL_INITIAL (decl) == error_mark_node)))
     return false;
   if (DECL_EXTERNAL (decl))
     return false;

Reply via email to