re PR target/44132 (emutls is broken under a range of circumstances.)
authorIain Sandoe <iains@gcc.gnu.org>
Mon, 24 May 2010 14:36:32 +0000 (14:36 +0000)
committerIain Sandoe <iains@gcc.gnu.org>
Mon, 24 May 2010 14:36:32 +0000 (14:36 +0000)
2010-05-24  Iain Sandoe  <iains@gcc.gnu.org>

PR target/44132
PR middle-end/43602
* varasm.c (get_emutls_init_templ_addr): Copy DECL_PRESERVE_P,
DECL_VISIBILITY_SPECIFIED.
(emutls_decl): Set DECL_PRESERVE_P and copy
DECL_VISIBILITY_SPECIFIED, DECL_RESTRICTED_P.
(emutls_finalize_control_var): New callback.
(emutls_finish): Finalize emutls control variables.
* toplev.c (compile_file): Move the call to emutls_finish ()
before varpool_assemble_pending_decls ().

From-SVN: r159781

gcc/ChangeLog
gcc/toplev.c
gcc/varasm.c

index 8313b2ceb6608ad64a6bc9b32624b6e4bfca1e2e..c82178cb25d4164e28c5ba95c3189d35810160f6 100644 (file)
@@ -1,3 +1,16 @@
+2010-05-24  Iain Sandoe  <iains@gcc.gnu.org>
+
+       PR target/44132
+       PR middle-end/43602
+       * varasm.c (get_emutls_init_templ_addr): Copy DECL_PRESERVE_P,
+       DECL_VISIBILITY_SPECIFIED.
+       (emutls_decl): Set DECL_PRESERVE_P and copy
+       DECL_VISIBILITY_SPECIFIED, DECL_RESTRICTED_P.
+       (emutls_finalize_control_var): New callback.
+       (emutls_finish): Finalize emutls control variables.
+       * toplev.c (compile_file): Move the call to emutls_finish () 
+       before varpool_assemble_pending_decls ().
+
 2010-05-24  Daniel Gutson  <dgutson@codesourcery.com>
 
        * config/arm/lib1funcs.asm (__ARM_ARCH__): __ARM_ARCH_7EM__
index 3cf65bad0777ca9a8c79da6b6212b940ab2f1b3a..fcd720dd9a98cbf1067132a04f39d0565bc6e680 100644 (file)
@@ -1063,6 +1063,11 @@ compile_file (void)
   if (errorcount || sorrycount)
     return;
 
+  /* Ensure that emulated TLS control vars are finalized and build 
+     a static constructor for them, when it is required.  */
+  if (!targetm.have_tls)
+    emutls_finish ();
+
   varpool_assemble_pending_decls ();
   finish_aliases_2 ();
 
@@ -1070,10 +1075,6 @@ compile_file (void)
   if (flag_mudflap)
     mudflap_finish_file ();
 
-  /* Likewise for emulated thread-local storage.  */
-  if (!targetm.have_tls)
-    emutls_finish ();
-
   output_shared_constant_pool ();
   output_object_blocks ();
 
index ef02994f315676552120f5447ae4fc92e10aee58..3f8fd02aa8f92f92d065dac0268e7112df564b8e 100644 (file)
@@ -314,13 +314,14 @@ get_emutls_init_templ_addr (tree decl)
   to = build_decl (DECL_SOURCE_LOCATION (decl),
                   VAR_DECL, name, TREE_TYPE (decl));
   SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to));
-  DECL_TLS_MODEL (to) = TLS_MODEL_EMULATED;
+
   DECL_ARTIFICIAL (to) = 1;
   TREE_USED (to) = TREE_USED (decl);
   TREE_READONLY (to) = 1;
   DECL_IGNORED_P (to) = 1;
   DECL_CONTEXT (to) = DECL_CONTEXT (decl);
   DECL_SECTION_NAME (to) = DECL_SECTION_NAME (decl);
+  DECL_PRESERVE_P (to) = DECL_PRESERVE_P (decl);
 
   DECL_WEAK (to) = DECL_WEAK (decl);
   if (DECL_ONE_ONLY (decl))
@@ -333,6 +334,7 @@ get_emutls_init_templ_addr (tree decl)
   else
     TREE_STATIC (to) = 1;
 
+  DECL_VISIBILITY_SPECIFIED (to) = DECL_VISIBILITY_SPECIFIED (decl);
   DECL_INITIAL (to) = DECL_INITIAL (decl);
   DECL_INITIAL (decl) = NULL;
 
@@ -385,6 +387,8 @@ emutls_decl (tree decl)
       DECL_TLS_MODEL (to) = TLS_MODEL_EMULATED;
       DECL_ARTIFICIAL (to) = 1;
       DECL_IGNORED_P (to) = 1;
+      /* FIXME: work around PR44132.  */
+      DECL_PRESERVE_P (to) = 1;
       TREE_READONLY (to) = 0;
       SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to));
       if (DECL_ONE_ONLY (decl))
@@ -412,6 +416,10 @@ emutls_decl (tree decl)
   DECL_COMMON (to) = DECL_COMMON (decl);
   DECL_WEAK (to) = DECL_WEAK (decl);
   DECL_VISIBILITY (to) = DECL_VISIBILITY (decl);
+  DECL_VISIBILITY_SPECIFIED (to) = DECL_VISIBILITY_SPECIFIED (decl);
+  
+  /* Fortran might pass this to us.  */
+  DECL_RESTRICTED_P (to) = DECL_RESTRICTED_P (decl);
 
   return to;
 }
@@ -450,16 +458,39 @@ emutls_common_1 (void **loc, void *xstmts)
   return 1;
 }
 
+/* Callback to finalize one emutls control variable.  */
+
+static int
+emutls_finalize_control_var (void **loc, 
+                               void *unused ATTRIBUTE_UNUSED)
+{
+  struct tree_map *h = *(struct tree_map **) loc;
+  if (h != NULL) 
+    {
+      struct varpool_node *node = varpool_node (h->to);
+      /* Because varpool_finalize_decl () has side-effects,
+         only apply to un-finalized vars.  */
+      if (node && !node->finalized) 
+       varpool_finalize_decl (h->to);
+    }
+  return 1;
+}
+
+/* Finalize emutls control vars and add a static constructor if
+   required.  */
+
 void
 emutls_finish (void)
 {
+  if (emutls_htab == NULL)
+    return;
+  htab_traverse_noresize (emutls_htab, 
+                         emutls_finalize_control_var, NULL);
+
   if (targetm.emutls.register_common)
     {
       tree body = NULL_TREE;
 
-      if (emutls_htab == NULL)
-       return;
-
       htab_traverse_noresize (emutls_htab, emutls_common_1, &body);
       if (body == NULL_TREE)
        return;