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 applied to sh.c: fix more struct layout failures



2005-08-19  J"orn Rennecke <joern.rennecke@st.com>

	* sh.c (find_sole_member): New function.
	(sh_gimplify_va_arg_expr): Use it. Allow RECORD_TYPE mode mismatch
	if the record's alignment is larger than the size of its only member.

Index: config/sh/sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.343
diff -p -r1.343 sh.c
*** config/sh/sh.c	18 Aug 2005 16:41:51 -0000	1.343
--- config/sh/sh.c	19 Aug 2005 12:25:07 -0000
*************** sh_va_start (tree valist, rtx nextarg)
*** 6632,6637 ****
--- 6632,6658 ----
    expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  }
  
+ /* TYPE is a RECORD_TYPE.  If there is only a single non-zero-sized
+    member, return it.  */
+ static tree
+ find_sole_member (tree type)
+ {
+   tree field, member = NULL_TREE;
+ 
+   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+     {
+       if (TREE_CODE (field) != FIELD_DECL)
+ 	continue;
+       if (!DECL_SIZE (field))
+ 	return NULL_TREE;
+       if (integer_zerop (DECL_SIZE (field)))
+ 	continue;
+       if (member)
+ 	return NULL_TREE;
+       member = field;
+     }
+   return member;
+ }
  /* Implement `va_arg'.  */
  
  static tree
*************** sh_gimplify_va_arg_expr (tree valist, tr
*** 6657,6662 ****
--- 6678,6684 ----
        tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack;
        int pass_as_float;
        tree lab_false;
+       tree member;
  
        f_next_o = TYPE_FIELDS (va_list_type_node);
        f_next_o_limit = TREE_CHAIN (f_next_o);
*************** sh_gimplify_va_arg_expr (tree valist, tr
*** 6679,6700 ****
  	 like their member.  This is relevant if the latter has a REAL_TYPE
  	 or COMPLEX_TYPE type.  */
        while (TREE_CODE (type) == RECORD_TYPE
! 	     && TYPE_FIELDS (type)
! 	     && TREE_CODE (TYPE_FIELDS (type)) == FIELD_DECL
! 	     && (TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == REAL_TYPE
! 		 || TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == COMPLEX_TYPE
! 		 || TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == RECORD_TYPE)
!              && TREE_CHAIN (TYPE_FIELDS (type)) == NULL_TREE)
  	{
! 	  tree field_type = TREE_TYPE (TYPE_FIELDS (type));
  
  	  if (TYPE_MODE (type) == TYPE_MODE (field_type))
  	    type = field_type;
  	  else
  	    {
! 	      gcc_assert (TYPE_ALIGN (type)
! 			  < GET_MODE_ALIGNMENT (TYPE_MODE (field_type)));
! 	    break;
  	    }
  	}
  
--- 6701,6722 ----
  	 like their member.  This is relevant if the latter has a REAL_TYPE
  	 or COMPLEX_TYPE type.  */
        while (TREE_CODE (type) == RECORD_TYPE
! 	     && (member = find_sole_member (type))
! 	     && (TREE_CODE (TREE_TYPE (member)) == REAL_TYPE
! 		 || TREE_CODE (TREE_TYPE (member)) == COMPLEX_TYPE
! 		 || TREE_CODE (TREE_TYPE (member)) == RECORD_TYPE))
  	{
! 	  tree field_type = TREE_TYPE (member);
  
  	  if (TYPE_MODE (type) == TYPE_MODE (field_type))
  	    type = field_type;
  	  else
  	    {
! 	      gcc_assert ((TYPE_ALIGN (type)
! 			   < GET_MODE_ALIGNMENT (TYPE_MODE (field_type)))
! 			  || (TYPE_ALIGN (type)
! 			      > GET_MODE_BITSIZE (TYPE_MODE (field_type))));
! 	      break;
  	    }
  	}
  

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