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 (gcc-3.3.4) PR-14142


I have back-ported a fix for PR-14142 from the main branch (3.5?) and applied 
it to the 3.3.4 release-candidate.  I took do_type_align() and layout_decl() 
from gcc/stor-layout.c, which no longer overrides the alignment as set by the 
attribute((alignment(N))).  I chose to take the functions entire, as that 
seemed to be the most exercised code that fixed the problem.

I have probably missed the boat for 3.3.4, but here is the patch anyway, in 
case there will be a 3.3.5.

There is no ChangeLog.  I can post one if the patch is approved.

Cheers.
GP


*** stor-layout.c	Tue Oct 14 14:43:04 2003
--- /home/gp/cvs/head/tools/gcc/gcc/stor-layout.c	Wed May 19 11:03:19 2004
*************** round_down (value, divisor)
*** 346,351 ****
--- 346,367 ----
    return size_binop (MULT_EXPR, size_binop (FLOOR_DIV_EXPR, value, arg), arg);
  }
  
+ /* Subroutine of layout_decl: Force alignment required for the data type.
+    But if the decl itself wants greater alignment, don't override that.  */
+ 
+ static inline void
+ do_type_align (type, decl)
+      tree type;
+      tree decl;
+ {
+   if (TYPE_ALIGN (type) > DECL_ALIGN (decl))
+     {
+       DECL_ALIGN (decl) = TYPE_ALIGN (type);
+       if (TREE_CODE (decl) == FIELD_DECL)
+ 	DECL_USER_ALIGN (decl) = TYPE_USER_ALIGN (type);
+     }
+ }
+ 
  /* Set the size, mode and alignment of a ..._DECL node.
     TYPE_DECL does need this for C++.
     Note that LABEL_DECL and CONST_DECL nodes do not need this,
*************** layout_decl (decl, known_align)
*** 398,468 ****
        DECL_SIZE (decl) = TYPE_SIZE (type);
        DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);
      }
!   else
      DECL_SIZE_UNIT (decl)
        = convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
  				       bitsize_unit_node));
  
!   /* Force alignment required for the data type.
!      But if the decl itself wants greater alignment, don't override that.
!      Likewise, if the decl is packed, don't override it.  */
!   if (! (code == FIELD_DECL && DECL_BIT_FIELD (decl))
!       && (DECL_ALIGN (decl) == 0
! 	  || (! (code == FIELD_DECL && DECL_PACKED (decl))
! 	      && TYPE_ALIGN (type) > DECL_ALIGN (decl))))
      {
!       DECL_ALIGN (decl) = TYPE_ALIGN (type);
!       DECL_USER_ALIGN (decl) = 0;
!     }
  
!   /* For fields, set the bit field type and update the alignment.  */
!   if (code == FIELD_DECL)
!     {
!       DECL_BIT_FIELD_TYPE (decl) = DECL_BIT_FIELD (decl) ? type : 0;
!       if (maximum_field_alignment != 0)
! 	DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), maximum_field_alignment);
  
        /* If the field is of variable size, we can't misalign it since we
  	 have no way to make a temporary to align the result.  But this
  	 isn't an issue if the decl is not addressable.  Likewise if it
! 	 is of unknown size.  */
!       else if (DECL_PACKED (decl)
! 	       && (DECL_NONADDRESSABLE_P (decl)
! 		   || DECL_SIZE_UNIT (decl) == 0
! 		   || TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST))
! 	{
! 	  DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);
! 	  DECL_USER_ALIGN (decl) = 0;
! 	}
!     }
  
!   /* See if we can use an ordinary integer mode for a bit-field.
!      Conditions are: a fixed size that is correct for another mode
!      and occupying a complete byte or bytes on proper boundary.  */
!   if (code == FIELD_DECL && DECL_BIT_FIELD (decl)
!       && TYPE_SIZE (type) != 0
!       && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
!       && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
!     {
!       enum machine_mode xmode
! 	= mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
  
!       if (xmode != BLKmode && known_align >= GET_MODE_ALIGNMENT (xmode))
  	{
! 	  DECL_ALIGN (decl) = MAX (GET_MODE_ALIGNMENT (xmode),
! 				   DECL_ALIGN (decl));
! 	  DECL_MODE (decl) = xmode;
! 	  DECL_BIT_FIELD (decl) = 0;
  	}
-     }
  
!   /* Turn off DECL_BIT_FIELD if we won't need it set.  */
!   if (code == FIELD_DECL && DECL_BIT_FIELD (decl)
!       && TYPE_MODE (type) == BLKmode && DECL_MODE (decl) == BLKmode
!       && known_align >= TYPE_ALIGN (type)
!       && DECL_ALIGN (decl) >= TYPE_ALIGN (type)
!       && DECL_SIZE_UNIT (decl) != 0)
!     DECL_BIT_FIELD (decl) = 0;
  
    /* Evaluate nonconstant size only once, either now or as soon as safe.  */
    if (DECL_SIZE (decl) != 0 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
--- 414,525 ----
        DECL_SIZE (decl) = TYPE_SIZE (type);
        DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);
      }
!   else if (DECL_SIZE_UNIT (decl) == 0)
      DECL_SIZE_UNIT (decl)
        = convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
  				       bitsize_unit_node));
  
!   if (code != FIELD_DECL)
!     /* For non-fields, update the alignment from the type.  */
!     do_type_align (type, decl);
!   else
!     /* For fields, it's a bit more complicated...  */
      {
!       bool old_user_align = DECL_USER_ALIGN (decl);
  
!       if (DECL_BIT_FIELD (decl))
! 	{
! 	  DECL_BIT_FIELD_TYPE (decl) = type;
! 
! 	  /* A zero-length bit-field affects the alignment of the next
! 	     field.  */
! 	  if (integer_zerop (DECL_SIZE (decl))
! 	      && ! DECL_PACKED (decl)
! 	      && ! targetm.ms_bitfield_layout_p (DECL_FIELD_CONTEXT (decl)))
! 	    {
! #ifdef PCC_BITFIELD_TYPE_MATTERS
! 	      if (PCC_BITFIELD_TYPE_MATTERS)
! 		do_type_align (type, decl);
! 	      else
! #endif
! 		{
! #ifdef EMPTY_FIELD_BOUNDARY
! 		  if (EMPTY_FIELD_BOUNDARY > DECL_ALIGN (decl))
! 		    {
! 		      DECL_ALIGN (decl) = EMPTY_FIELD_BOUNDARY;
! 		      DECL_USER_ALIGN (decl) = 0;
! 		    }
! #endif
! 		}
! 	    }
! 
! 	  /* See if we can use an ordinary integer mode for a bit-field.
! 	     Conditions are: a fixed size that is correct for another mode
! 	     and occupying a complete byte or bytes on proper boundary.  */
! 	  if (TYPE_SIZE (type) != 0
! 	      && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
! 	      && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
! 	    {
! 	      enum machine_mode xmode
! 		= mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
! 
! 	      if (xmode != BLKmode 
! 		  && (known_align == 0
! 		      || known_align >= GET_MODE_ALIGNMENT (xmode)))
! 		{
! 		  DECL_ALIGN (decl) = MAX (GET_MODE_ALIGNMENT (xmode),
! 					   DECL_ALIGN (decl));
! 		  DECL_MODE (decl) = xmode;
! 		  DECL_BIT_FIELD (decl) = 0;
! 		}
! 	    }
! 
! 	  /* Turn off DECL_BIT_FIELD if we won't need it set.  */
! 	  if (TYPE_MODE (type) == BLKmode && DECL_MODE (decl) == BLKmode
! 	      && known_align >= TYPE_ALIGN (type)
! 	      && DECL_ALIGN (decl) >= TYPE_ALIGN (type))
! 	    DECL_BIT_FIELD (decl) = 0;
! 	}
!       else if (DECL_PACKED (decl) && DECL_USER_ALIGN (decl))
! 	/* Don't touch DECL_ALIGN.  For other packed fields, go ahead and
! 	   round up; we'll reduce it again below.  We want packing to
! 	   supersede USER_ALIGN inherited from the type, but defer to
! 	   alignment explicitly specified on the field decl.  */;
!       else
! 	do_type_align (type, decl);
  
        /* If the field is of variable size, we can't misalign it since we
  	 have no way to make a temporary to align the result.  But this
  	 isn't an issue if the decl is not addressable.  Likewise if it
! 	 is of unknown size.
  
! 	 Note that do_type_align may set DECL_USER_ALIGN, so we need to
! 	 check old_user_align instead.  */
!       if (DECL_PACKED (decl)
! 	  && !old_user_align
! 	  && (DECL_NONADDRESSABLE_P (decl)
! 	      || DECL_SIZE_UNIT (decl) == 0
! 	      || TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST))
! 	DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);
  
!       if (! DECL_USER_ALIGN (decl) && ! DECL_PACKED (decl))
  	{
! 	  /* Some targets (i.e. i386, VMS) limit struct field alignment
! 	     to a lower boundary than alignment of variables unless
! 	     it was overridden by attribute aligned.  */
! #ifdef BIGGEST_FIELD_ALIGNMENT
! 	  DECL_ALIGN (decl)
! 	    = MIN (DECL_ALIGN (decl), (unsigned) BIGGEST_FIELD_ALIGNMENT);
! #endif
! #ifdef ADJUST_FIELD_ALIGN
! 	  DECL_ALIGN (decl) = ADJUST_FIELD_ALIGN (decl, DECL_ALIGN (decl));
! #endif
  	}
  
!       /* Should this be controlled by DECL_USER_ALIGN, too?  */
!       if (maximum_field_alignment != 0)
! 	DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), maximum_field_alignment);
!     }
  
    /* Evaluate nonconstant size only once, either now or as soon as safe.  */
    if (DECL_SIZE (decl) != 0 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
*************** layout_decl (decl, known_align)
*** 481,493 ****
        if (size != 0 && TREE_CODE (size) == INTEGER_CST
  	  && compare_tree_int (size, larger_than_size) > 0)
  	{
! 	  unsigned int size_as_int = TREE_INT_CST_LOW (size);
  
  	  if (compare_tree_int (size, size_as_int) == 0)
! 	    warning_with_decl (decl, "size of `%s' is %d bytes", size_as_int);
  	  else
! 	    warning_with_decl (decl, "size of `%s' is larger than %d bytes",
! 			       larger_than_size);
  	}
      }
  
--- 538,550 ----
        if (size != 0 && TREE_CODE (size) == INTEGER_CST
  	  && compare_tree_int (size, larger_than_size) > 0)
  	{
! 	  int size_as_int = TREE_INT_CST_LOW (size);
  
  	  if (compare_tree_int (size, size_as_int) == 0)
! 	    warning ("%Jsize of '%D' is %d bytes", decl, decl, size_as_int);
  	  else
! 	    warning ("%Jsize of '%D' is larger than %d bytes",
!                      decl, decl, larger_than_size);
  	}
      }
  

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