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 alignment bug


Hi,

This patch fixes one of the alignment issues in the Ada compiler, a 
regression introduced by 

2002-05-06  Richard Henderson  <rth@redhat.com>

        PR c++/6212
        * expr.c (highest_pow2_factor_for_type): New.
        (expand_assignment): Use it.

which authoritatively augments the alignment of an object based on its type.


Unfortunately this is wrong for packed fields in aggregates, as Richard 
correctly suggested in

   http://gcc.gnu.org/ml/gcc/2002-05/msg00514.html

The problem shows up only in corner cases for C-type languages, but is more 
common in Ada because of the semantics of packed aggregates.

The following (admittedly convoluted) C testcase

void foo(int n)
{
  struct S {
    int i[n];
    unsigned int b:1;
    int i2;
  } __attribute__ ((packed)) __attribute__ ((aligned (4)));

  struct S s;

  s.i2 = 0;
}

gives an unaligned memory access for 's.i2 = 0' on SPARC, a regression from 
GCC 2.95.3 present on all active branches.


The proposed fix is to use DECL_ALIGN instead of TYPE_ALIGN for components of 
aggregates, so that the packed-ness is correctly taken into account.

Bootstrapped/regtested on i586-redhat-linux, sparc-sun-solaris2.8 and 
sparc64-sun-solaris2.9 (3.4 branch).  OK for mainline and 3.4 branch?


2004-02-28  Eric Botcazou  <ebotcazou@act-europe.fr>

	* expr.c (highest_pow2_factor_for_type): Rename into
	highest_pow2_factor_for_target.  Use DECL_ALIGN instead of
	TYPE_ALIGN when the target is a COMPONENT_REF.
	(expand_assignment): Ajust call to highest_pow2_factor_for_type.


2004-02-28  Eric Botcazou  <ebotcazou@act-europe.fr>

	* gcc.c-torture/execute/20040228-1.c: New test.


-- 
Eric Botcazou
/* This used to fail on SPARC with an unaligned memory access.  */

void foo(int n)
{
  struct S {
    int i[n];
    unsigned int b:1;
    int i2;
  } __attribute__ ((packed)) __attribute__ ((aligned (4)));

  struct S s;

  s.i2 = 0;
}

int main(void)
{
  foo(4);
  
  return 0;
}
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.615.4.5
diff -c -p -r1.615.4.5 expr.c
*** expr.c	27 Feb 2004 08:14:59 -0000	1.615.4.5
--- expr.c	28 Feb 2004 22:29:13 -0000
*************** static rtx store_field (rtx, HOST_WIDE_I
*** 161,167 ****
  static rtx var_rtx (tree);
  
  static unsigned HOST_WIDE_INT highest_pow2_factor (tree);
! static unsigned HOST_WIDE_INT highest_pow2_factor_for_type (tree, tree);
  
  static int is_aligning_offset (tree, tree);
  static rtx expand_increment (tree, int, int);
--- 161,167 ----
  static rtx var_rtx (tree);
  
  static unsigned HOST_WIDE_INT highest_pow2_factor (tree);
! static unsigned HOST_WIDE_INT highest_pow2_factor_for_target (tree, tree);
  
  static int is_aligning_offset (tree, tree);
  static rtx expand_increment (tree, int, int);
*************** expand_assignment (tree to, tree from, i
*** 3800,3807 ****
  	    }
  
  	  to_rtx = offset_address (to_rtx, offset_rtx,
! 				   highest_pow2_factor_for_type (TREE_TYPE (to),
! 								 offset));
  	}
  
        if (GET_CODE (to_rtx) == MEM)
--- 3800,3807 ----
  	    }
  
  	  to_rtx = offset_address (to_rtx, offset_rtx,
! 				   highest_pow2_factor_for_target (to,
! 				   				   offset));
  	}
  
        if (GET_CODE (to_rtx) == MEM)
*************** highest_pow2_factor (tree exp)
*** 6031,6047 ****
    return 1;
  }
  
! /* Similar, except that it is known that the expression must be a multiple
!    of the alignment of TYPE.  */
  
  static unsigned HOST_WIDE_INT
! highest_pow2_factor_for_type (tree type, tree exp)
  {
!   unsigned HOST_WIDE_INT type_align, factor;
  
    factor = highest_pow2_factor (exp);
!   type_align = TYPE_ALIGN (type) / BITS_PER_UNIT;
!   return MAX (factor, type_align);
  }
  
  /* Return an object on the placeholder list that matches EXP, a
--- 6031,6052 ----
    return 1;
  }
  
! /* Similar, except that the alignment requirements of TARGET are
!    taken into account.  Assume it is at least as aligned as its
!    type, unless it is a COMPONENT_REF in which case the layout of
!    the structure gives the alignment.  */
  
  static unsigned HOST_WIDE_INT
! highest_pow2_factor_for_target (tree target, tree exp)
  {
!   unsigned HOST_WIDE_INT target_align, factor;
  
    factor = highest_pow2_factor (exp);
!   if (TREE_CODE (target) == COMPONENT_REF)
!     target_align = DECL_ALIGN (TREE_OPERAND (target, 1)) / BITS_PER_UNIT;
!   else
!     target_align = TYPE_ALIGN (TREE_TYPE (target)) / BITS_PER_UNIT;
!   return MAX (factor, target_align);
  }
  
  /* Return an object on the placeholder list that matches EXP, a

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