From ceadb728b046622ad72dcd5df7fc8cba2767c09b Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 27 May 2009 16:06:44 +0000 Subject: [PATCH] expr.c (target_align): New function. * expr.c (target_align): New function. Alignment the TARGET of an assignment may be assume to have. (highest_pow2_factor_for_target): Use it instead of relying on immediate tree attributes of TARGET, not necessarily honored when intermediate bitfields are involved. testsuite/ * gcc.c-torture/execute/align-nest.c: New testcase. * gnat.dg/misaligned_nest.adb: New testcase. Co-Authored-By: Eric Botcazou From-SVN: r147916 --- gcc/ChangeLog | 8 +++ gcc/expr.c | 51 ++++++++++++++++--- gcc/testsuite/ChangeLog | 6 +++ .../gcc.c-torture/execute/align-nest.c | 28 ++++++++++ gcc/testsuite/gnat.dg/misaligned_nest.adb | 26 ++++++++++ 5 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/align-nest.c create mode 100644 gcc/testsuite/gnat.dg/misaligned_nest.adb diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3d9a9b35ae6..2be0ee95914 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2009-05-28 Olivier Hainque + + * expr.c (target_align): New function. Alignment the TARGET of an + assignment may be assume to have. + (highest_pow2_factor_for_target): Use it instead of relying on + immediate tree attributes of TARGET, not necessarily honored when + intermediate bitfields are involved. + 2009-05-27 H.J. Lu PR target/40266 diff --git a/gcc/expr.c b/gcc/expr.c index fd27483d011..1ecdb0277d2 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -6224,6 +6224,45 @@ component_ref_field_offset (tree exp) else return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp); } + +/* Alignment in bits the TARGET of an assignment may be assumed to have. */ + +static unsigned HOST_WIDE_INT +target_align (const_tree target) +{ + /* We might have a chain of nested references with intermediate misaligning + bitfields components, so need to recurse to find out. */ + + unsigned HOST_WIDE_INT this_align, outer_align; + + switch (TREE_CODE (target)) + { + case BIT_FIELD_REF: + return 1; + + case COMPONENT_REF: + this_align = DECL_ALIGN (TREE_OPERAND (target, 1)); + outer_align = target_align (TREE_OPERAND (target, 0)); + return MIN (this_align, outer_align); + + case ARRAY_REF: + case ARRAY_RANGE_REF: + this_align = TYPE_ALIGN (TREE_TYPE (target)); + outer_align = target_align (TREE_OPERAND (target, 0)); + return MIN (this_align, outer_align); + + CASE_CONVERT: + case NON_LVALUE_EXPR: + case VIEW_CONVERT_EXPR: + this_align = TYPE_ALIGN (TREE_TYPE (target)); + outer_align = target_align (TREE_OPERAND (target, 0)); + return MAX (this_align, outer_align); + + default: + return TYPE_ALIGN (TREE_TYPE (target)); + } +} + /* Given an rtx VALUE that may contain additions and multiplications, return an equivalent value that just refers to a register, memory, or constant. @@ -6670,14 +6709,10 @@ highest_pow2_factor (const_tree exp) static unsigned HOST_WIDE_INT highest_pow2_factor_for_target (const_tree target, const_tree exp) { - unsigned HOST_WIDE_INT target_align, factor; - - factor = highest_pow2_factor (exp); - if (TREE_CODE (target) == COMPONENT_REF) - target_align = DECL_ALIGN_UNIT (TREE_OPERAND (target, 1)); - else - target_align = TYPE_ALIGN_UNIT (TREE_TYPE (target)); - return MAX (factor, target_align); + unsigned HOST_WIDE_INT talign = target_align (target) / BITS_PER_UNIT; + unsigned HOST_WIDE_INT factor = highest_pow2_factor (exp); + + return MAX (factor, talign); } /* Return &VAR expression for emulated thread local VAR. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f54f138eeb6..0cc0a1000e4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2009-05-28 Olivier Hainque + Eric Botcazou + + * gcc.c-torture/execute/align-nest.c: New testcase. + * gnat.dg/misaligned_nest.adb: New testcase. + 2009-05-27 Rafael Avila de Espindola * g++.dg/plugin/attribute_plugin.c: Include gcc-plugin.h first. diff --git a/gcc/testsuite/gcc.c-torture/execute/align-nest.c b/gcc/testsuite/gcc.c-torture/execute/align-nest.c new file mode 100644 index 00000000000..2ff2952c70c --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/align-nest.c @@ -0,0 +1,28 @@ + +void foo(int n) +{ + typedef struct + { + int value; + } myint; + + struct S + { + int i[n]; + unsigned int b:1; + myint mi; + } __attribute__ ((packed)) __attribute__ ((aligned (4))); + + struct S s[2]; + int k; + + for (k = 0; k < 2; k ++) + s[k].mi.value = 0; +} + +int main () +{ + foo (2); + return 0; +} + diff --git a/gcc/testsuite/gnat.dg/misaligned_nest.adb b/gcc/testsuite/gnat.dg/misaligned_nest.adb new file mode 100644 index 00000000000..3b6fd845da4 --- /dev/null +++ b/gcc/testsuite/gnat.dg/misaligned_nest.adb @@ -0,0 +1,26 @@ +-- { dg-do run } +-- { dg-options "-gnatp" } + +procedure Misaligned_Nest is + + type Int is record + V : Integer; + end record; + + type Block is record + B : Boolean; + I : Int; + end record; + pragma Pack (Block); + for Block'Alignment use 1; + + type Pair is array (1 .. 2) of Block; + + P : Pair; +begin + for K in P'Range loop + P(K).I.V := 1; + end loop; +end; + +