This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH][LTO] Fix PR60720


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  <rguenther@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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]