Hi,
newer Firefox trees fails to build because jsmalloc contain variable that is
declared as tls-initial-exec in one unit but used as tls-global-dynamic
in others.

As discussed with Jakub on IRC, the linker supports some model transitions,
so we should do the same in symtab.c too.

Bootstrapped/regtested x86_64-linux, tested on firefox, comitted.

Honza

        * lto-symtab.c (lto_varpool_replace_node): Merge TLS models.
Index: lto-symtab.c
===================================================================
--- lto-symtab.c        (revision 220212)
+++ lto-symtab.c        (working copy)
@@ -158,11 +158,44 @@ lto_varpool_replace_node (varpool_node *
 
   if (vnode->tls_model != prevailing_node->tls_model)
     {
-      error_at (DECL_SOURCE_LOCATION (vnode->decl),
-               "%qD is defined as %s", vnode->decl, tls_model_names 
[vnode->tls_model]);
-      inform (DECL_SOURCE_LOCATION (prevailing_node->decl),
-             "previously defined here as %s",
-             tls_model_names [prevailing_node->tls_model]);
+      bool error = false;
+
+      /* Non-TLS and TLS never mix together.  Also emulated model is not
+        compatible with anything else.  */
+      if (prevailing_node->tls_model == TLS_MODEL_NONE
+         || prevailing_node->tls_model == TLS_MODEL_EMULATED
+         || vnode->tls_model == TLS_MODEL_NONE
+         || vnode->tls_model == TLS_MODEL_EMULATED)
+       error = true;
+      /* Linked is silently supporting transitions
+        GD -> IE, GD -> LE, LD -> LE, IE -> LE, LD -> IE.
+        Do the same transitions and error out on others.  */
+      else if ((prevailing_node->tls_model == TLS_MODEL_REAL
+               || prevailing_node->tls_model == TLS_MODEL_LOCAL_DYNAMIC)
+              && (vnode->tls_model == TLS_MODEL_INITIAL_EXEC
+                  || vnode->tls_model == TLS_MODEL_LOCAL_EXEC))
+       prevailing_node->tls_model = vnode->tls_model;
+      else if ((vnode->tls_model == TLS_MODEL_REAL
+               || vnode->tls_model == TLS_MODEL_LOCAL_DYNAMIC)
+              && (prevailing_node->tls_model == TLS_MODEL_INITIAL_EXEC
+                  || prevailing_node->tls_model == TLS_MODEL_LOCAL_EXEC))
+       ;
+      else if (prevailing_node->tls_model == TLS_MODEL_INITIAL_EXEC
+              && vnode->tls_model == TLS_MODEL_LOCAL_EXEC)
+       prevailing_node->tls_model = vnode->tls_model;
+      else if (vnode->tls_model == TLS_MODEL_INITIAL_EXEC
+              && prevailing_node->tls_model == TLS_MODEL_LOCAL_EXEC)
+       ;
+      else
+       error = true;
+      if (error)
+       {
+         error_at (DECL_SOURCE_LOCATION (vnode->decl),
+                   "%qD is defined with tls model %s", vnode->decl, 
tls_model_names [vnode->tls_model]);
+         inform (DECL_SOURCE_LOCATION (prevailing_node->decl),
+                 "previously defined here as %s",
+                 tls_model_names [prevailing_node->tls_model]);
+       }
     }
   /* Finally remove the replaced node.  */
   vnode->remove ();

Reply via email to