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]

[PATCH] Fix PR44889, merging of functions with incomplete aggregate arguments/return vals


This supports incomplete aggregate returns/args similar to
incomplete pointed-to aggregates.  We can conveniently re-use
the same code, so I split it out into a helper.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2010-07-09  Richard Guenther  <rguenther@suse.de>

	PR lto/44889
	* gimple.c (gimple_fixup_complete_and_incomplete_subtype_p): New
	helper function.
	(gimple_types_compatible_p): Similar to pointed-to
	types allow and merge a mix of complete and incomplete aggregate.
	Use gimple_fixup_complete_and_incomplete_subtype_p for that.
	(iterative_hash_gimple_type): Adjust for that.

	* gcc.dg/lto/20100709-1_0.c: New testcase.
	* gcc.dg/lto/20100709-1_1.c: Likewise.

Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c	(revision 162017)
--- gcc/gimple.c	(working copy)
*************** gimple_queue_type_fixup (tree context, t
*** 3343,3348 ****
--- 3343,3387 ----
    VEC_safe_push (type_fixup, heap, gimple_register_type_fixups, &f);
  }
  
+ /* If the type *T1P and the type *T2P are a complete and an incomplete
+    variant of the same type return true and queue a fixup for the
+    incomplete one and its CONTEXT.  Return false otherwise.  */
+ 
+ static bool
+ gimple_fixup_complete_and_incomplete_subtype_p (tree context1, tree *t1p,
+ 						tree context2, tree *t2p)
+ {
+   tree t1 = *t1p;
+   tree t2 = *t2p;
+ 
+   /* If one pointer points to an incomplete type variant of
+      the other pointed-to type they are the same.  */
+   if (TREE_CODE (t1) == TREE_CODE (t2)
+       && RECORD_OR_UNION_TYPE_P (t1)
+       && (!COMPLETE_TYPE_P (t1)
+ 	  || !COMPLETE_TYPE_P (t2))
+       && TYPE_QUALS (t1) == TYPE_QUALS (t2)
+       && compare_type_names_p (TYPE_MAIN_VARIANT (t1),
+ 			       TYPE_MAIN_VARIANT (t2), true))
+     {
+       /* Replace the pointed-to incomplete type with the complete one.
+ 	 ???  This simple name-based merging causes at least some
+ 	 of the ICEs in canonicalizing FIELD_DECLs during stmt
+ 	 read.  For example in GCC we have two different struct deps
+ 	 and we mismatch the use in struct cpp_reader in sched-int.h
+ 	 vs. mkdeps.c.  Of course the whole exercise is for TBAA
+ 	 with structs which contain pointers to incomplete types
+ 	 in one unit and to complete ones in another.  So we
+ 	 probably should merge these types only with more context.  */
+       if (COMPLETE_TYPE_P (t2))
+ 	gimple_queue_type_fixup (context1, t1p, t2);
+       else
+ 	gimple_queue_type_fixup (context2, t2p, t1);
+       return true;
+     }
+   return false;
+ }
+ 
  /* Return 1 iff T1 and T2 are structurally identical.
     Otherwise, return 0.  */
  
*************** gimple_types_compatible_p (tree t1, tree
*** 3507,3539 ****
      case FUNCTION_TYPE:
        /* Function types are the same if the return type and arguments types
  	 are the same.  */
!       if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
  	goto different_types;
        else
  	{
! 	  if (!targetm.comp_type_attributes (t1, t2))
! 	    goto different_types;
  
! 	  if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
! 	    goto same_types;
! 	  else
  	    {
! 	      tree parms1, parms2;
! 
! 	      for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
! 		   parms1 && parms2;
! 		   parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
! 		{
! 		  if (!gimple_types_compatible_p (TREE_VALUE (parms1),
! 					     TREE_VALUE (parms2)))
! 		    goto different_types;
! 		}
! 
! 	      if (parms1 || parms2)
  		goto different_types;
- 
- 	      goto same_types;
  	    }
  	}
  
      case OFFSET_TYPE:
--- 3546,3580 ----
      case FUNCTION_TYPE:
        /* Function types are the same if the return type and arguments types
  	 are the same.  */
!       if (!gimple_fixup_complete_and_incomplete_subtype_p
! 	     (t1, &TREE_TYPE (t1), t2, &TREE_TYPE (t2))
! 	  && !gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
! 	goto different_types;
! 
!       if (!targetm.comp_type_attributes (t1, t2))
  	goto different_types;
+ 
+       if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
+ 	goto same_types;
        else
  	{
! 	  tree parms1, parms2;
  
! 	  for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
! 	       parms1 && parms2;
! 	       parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
  	    {
! 	      if (!gimple_fixup_complete_and_incomplete_subtype_p
! 		    (t1, &TREE_VALUE (parms1), t2, &TREE_VALUE (parms2))
! 		  && !gimple_types_compatible_p (TREE_VALUE (parms1),
! 						 TREE_VALUE (parms2)))
  		goto different_types;
  	    }
+ 
+ 	  if (parms1 || parms2)
+ 	    goto different_types;
+ 
+ 	  goto same_types;
  	}
  
      case OFFSET_TYPE:
*************** gimple_types_compatible_p (tree t1, tree
*** 3556,3585 ****
  
  	/* If one pointer points to an incomplete type variant of
  	   the other pointed-to type they are the same.  */
! 	if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))
! 	    && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t1))
! 	    && (!COMPLETE_TYPE_P (TREE_TYPE (t1))
! 		|| !COMPLETE_TYPE_P (TREE_TYPE (t2)))
! 	    && TYPE_QUALS (TREE_TYPE (t1)) == TYPE_QUALS (TREE_TYPE (t2))
! 	    && compare_type_names_p (TYPE_MAIN_VARIANT (TREE_TYPE (t1)),
! 				     TYPE_MAIN_VARIANT (TREE_TYPE (t2)), true))
! 	  {
! 	    /* Replace the pointed-to incomplete type with the
! 	       complete one.
! 	       ???  This simple name-based merging causes at least some
! 	       of the ICEs in canonicalizing FIELD_DECLs during stmt
! 	       read.  For example in GCC we have two different struct deps
! 	       and we mismatch the use in struct cpp_reader in sched-int.h
! 	       vs. mkdeps.c.  Of course the whole exercise is for TBAA
! 	       with structs which contain pointers to incomplete types
! 	       in one unit and to complete ones in another.  So we
! 	       probably should merge these types only with more context.  */
! 	    if (COMPLETE_TYPE_P (TREE_TYPE (t2)))
! 	      gimple_queue_type_fixup (t1, &TREE_TYPE (t1), TREE_TYPE (t2));
! 	    else
! 	      gimple_queue_type_fixup (t2, &TREE_TYPE (t2), TREE_TYPE (t1));
! 	    goto same_types;
! 	  }
  
  	/* Otherwise, pointer and reference types are the same if the
  	   pointed-to types are the same.  */
--- 3597,3605 ----
  
  	/* If one pointer points to an incomplete type variant of
  	   the other pointed-to type they are the same.  */
! 	if (gimple_fixup_complete_and_incomplete_subtype_p
! 	      (t1, &TREE_TYPE (t1), t2, &TREE_TYPE (t2)))
! 	  goto same_types;
  
  	/* Otherwise, pointer and reference types are the same if the
  	   pointed-to types are the same.  */
*************** iterative_hash_gimple_type (tree type, h
*** 3900,3912 ****
  	v = visit (TYPE_METHOD_BASETYPE (type), state, v,
  		   sccstack, sccstate, sccstate_obstack);
  
!       v = visit (TREE_TYPE (type), state, v,
! 		 sccstack, sccstate, sccstate_obstack);
  
        for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
  	{
! 	  v = visit (TREE_VALUE (p), state, v,
! 		     sccstack, sccstate, sccstate_obstack);
  	  na++;
  	}
  
--- 3920,3948 ----
  	v = visit (TYPE_METHOD_BASETYPE (type), state, v,
  		   sccstack, sccstate, sccstate_obstack);
  
!       /* For result types allow mismatch in completeness.  */
!       if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
! 	{
! 	  v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
! 	  v = iterative_hash_name
! 	      (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (type))), v);
! 	}
!       else
! 	v = visit (TREE_TYPE (type), state, v,
! 		   sccstack, sccstate, sccstate_obstack);
  
        for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
  	{
! 	  /* For argument types allow mismatch in completeness.  */
! 	  if (RECORD_OR_UNION_TYPE_P (TREE_VALUE (p)))
! 	    {
! 	      v = iterative_hash_hashval_t (TREE_CODE (TREE_VALUE (p)), v);
! 	      v = iterative_hash_name
! 		  (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_VALUE (p))), v);
! 	    }
! 	  else
! 	    v = visit (TREE_VALUE (p), state, v,
! 		       sccstack, sccstate, sccstate_obstack);
  	  na++;
  	}
  
Index: gcc/testsuite/gcc.dg/lto/20100709-1_0.c
===================================================================
*** gcc/testsuite/gcc.dg/lto/20100709-1_0.c	(revision 0)
--- gcc/testsuite/gcc.dg/lto/20100709-1_0.c	(revision 0)
***************
*** 0 ****
--- 1,7 ----
+ /* { dg-lto-do link } */
+ 
+ struct X;
+ struct Y {
+     struct X (*fnptr)(struct X);
+ };
+ struct Y foo;
Index: gcc/testsuite/gcc.dg/lto/20100709-1_1.c
===================================================================
*** gcc/testsuite/gcc.dg/lto/20100709-1_1.c	(revision 0)
--- gcc/testsuite/gcc.dg/lto/20100709-1_1.c	(revision 0)
***************
*** 0 ****
--- 1,11 ----
+ struct X { int i; };
+ struct Y {
+     struct X (*fnptr)(struct X);
+ };
+ extern struct Y foo;
+ int main()
+ {
+   struct X x;
+   foo.fnptr(x);
+   return 0;
+ }


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