On Mon, 31 Mar 2014, Richard Biener wrote:

> 
> The following patch makes sure we wrap symbol references in global
> initializers the same as we do for IL references - inside a MEM_REF
> that guards their context against type changes due to symbol merging
> (and thus in this case against ICEs when processing an ARRAY_REF
> around a non-array object).
> 
> LTO bootstrap & regtest running on x86_64-unknown-linux-gnu.

It turns out that changing the tree structure while doing a DFS
walk is a bad idea so the following patch instead does it at
lto_output time (and restricts it to necessary cases, 
handled-component-refs wrapping the decls).

LTO bootstrapped and tested on x86_64-unknown-linux-gnu, queued for 
stage1.

Richard.

2014-04-01  Richard Biener  <rguent...@suse.de>

        PR lto/60720
        * lto-streamer-out.c (wrap_refs): New function.
        (lto_output): Wrap symbol references in global initializes in
        type-preserving MEM_REFs.

        * gcc.dg/lto/pr60720_0.c: New testcase.
        * gcc.dg/lto/pr60720_1.c: Likewise.

Index: gcc/lto-streamer-out.c
===================================================================
*** gcc/lto-streamer-out.c      (revision 208955)
--- gcc/lto-streamer-out.c      (working copy)
*************** copy_function (struct cgraph_node *node)
*** 2024,2029 ****
--- 2024,2052 ----
    lto_end_section ();
  }
  
+ /* Wrap symbol references in *TP inside a type-preserving MEM_REF.  */
+ 
+ static tree
+ wrap_refs (tree *tp, int *ws, void *)
+ {
+   tree t = *tp;
+   if (handled_component_p (t)
+       && TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
+     {
+       tree decl = TREE_OPERAND (t, 0);
+       tree ptrtype = build_pointer_type (TREE_TYPE (decl));
+       TREE_OPERAND (t, 0) = build2 (MEM_REF, TREE_TYPE (decl),
+                                   build1 (ADDR_EXPR, ptrtype, decl),
+                                   build_int_cst (ptrtype, 0));
+       TREE_THIS_VOLATILE (TREE_OPERAND (t, 0)) = TREE_THIS_VOLATILE (decl);
+       *ws = 0;
+     }
+   else if (TREE_CODE (t) == CONSTRUCTOR)
+     ;
+   else if (!EXPR_P (t))
+     *ws = 0;
+   return NULL_TREE;
+ }
  
  /* Main entry point from the pass manager.  */
  
*************** lto_output (void)
*** 2045,2068 ****
    for (i = 0; i < n_nodes; i++)
      {
        symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
!       cgraph_node *node = dyn_cast <cgraph_node> (snode);
!       if (node
!         && lto_symtab_encoder_encode_body_p (encoder, node)
!         && !node->alias)
        {
  #ifdef ENABLE_CHECKING
!         gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl)));
!         bitmap_set_bit (output, DECL_UID (node->decl));
  #endif
!         decl_state = lto_new_out_decl_state ();
!         lto_push_out_decl_state (decl_state);
!         if (gimple_has_body_p (node->decl) || !flag_wpa)
!           output_function (node);
!         else
!           copy_function (node);
!         gcc_assert (lto_get_out_decl_state () == decl_state);
!         lto_pop_out_decl_state ();
!         lto_record_function_out_decl_state (node->decl, decl_state);
        }
      }
  
--- 2068,2100 ----
    for (i = 0; i < n_nodes; i++)
      {
        symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
!       if (cgraph_node *node = dyn_cast <cgraph_node> (snode))
        {
+         if (lto_symtab_encoder_encode_body_p (encoder, node)
+             && !node->alias)
+           {
  #ifdef ENABLE_CHECKING
!             gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl)));
!             bitmap_set_bit (output, DECL_UID (node->decl));
  #endif
!             decl_state = lto_new_out_decl_state ();
!             lto_push_out_decl_state (decl_state);
!             if (gimple_has_body_p (node->decl) || !flag_wpa)
!               output_function (node);
!             else
!               copy_function (node);
!             gcc_assert (lto_get_out_decl_state () == decl_state);
!             lto_pop_out_decl_state ();
!             lto_record_function_out_decl_state (node->decl, decl_state);
!           }
!       }
!       else if (varpool_node *node = dyn_cast <varpool_node> (snode))
!       {
!         /* Wrap symbol references inside the ctor in a type
!            preserving MEM_REF.  */
!         tree ctor = DECL_INITIAL (node->decl);
!         if (ctor && !in_lto_p)
!           walk_tree (&ctor, wrap_refs, NULL, NULL);
        }
      }
  
Index: gcc/testsuite/gcc.dg/lto/pr60720_0.c
===================================================================
*** gcc/testsuite/gcc.dg/lto/pr60720_0.c        (revision 0)
--- gcc/testsuite/gcc.dg/lto/pr60720_0.c        (working copy)
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-lto-do run } */
+ /* { dg-extra-ld-options { -w } } */
+ 
+ /* ???  lto.exp does not allow to scan for
+    :1:12: warning: type of 'x' does not match original declaration
+     extern int x[];
+                ^
+    :1:5: note: previously declared here
+     int x;
+         ^  */
+ 
+ extern int x[];
+ int *foo[] = { &x[0] };
+ 
+ int main() { return *foo[0]; }
Index: gcc/testsuite/gcc.dg/lto/pr60720_1.c
===================================================================
*** gcc/testsuite/gcc.dg/lto/pr60720_1.c        (revision 0)
--- gcc/testsuite/gcc.dg/lto/pr60720_1.c        (working copy)
***************
*** 0 ****
--- 1 ----
+ int x;

Reply via email to