This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix alignment bug
- From: Eric Botcazou <ebotcazou at act-europe dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 28 Feb 2004 23:37:25 +0100
- Subject: [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