From 3cef948a814542119083003a3c35a24e036230b6 Mon Sep 17 00:00:00 2001 From: ebotcazou Date: Tue, 3 Apr 2012 17:59:07 +0000 Subject: [PATCH] * expr.c (get_bit_range): Add OFFSET parameter and adjust BITPOS. Change type of BITOFFSET to signed. Make sure the lower bound of the computed range is non-negative by adjusting OFFSET and BITPOS. (expand_assignment): Adjust call to get_bit_range. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186110 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 +++++++ gcc/expr.c | 35 ++++++++++++++++++++++++++++------- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gnat.dg/pack18.adb | 12 ++++++++++++ gcc/testsuite/gnat.dg/pack18_pkg.ads | 21 +++++++++++++++++++++ 5 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/pack18.adb create mode 100644 gcc/testsuite/gnat.dg/pack18_pkg.ads diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e1fc73b..e20c0e4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2012-04-03 Eric Botcazou + + * expr.c (get_bit_range): Add OFFSET parameter and adjust BITPOS. + Change type of BITOFFSET to signed. Make sure the lower bound of + the computed range is non-negative by adjusting OFFSET and BITPOS. + (expand_assignment): Adjust call to get_bit_range. + 2012-04-03 Sandeep Kumar Singh * h8300/h8300.c (h8300_current_function_monitor_function_p): diff --git a/gcc/expr.c b/gcc/expr.c index 56ec3fa..6caee3b 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -4431,19 +4431,22 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize, /* In the C++ memory model, consecutive bit fields in a structure are considered one memory location. - Given a COMPONENT_REF EXP at bit position BITPOS, this function + Given a COMPONENT_REF EXP at position (BITPOS, OFFSET), this function returns the bit range of consecutive bits in which this COMPONENT_REF - belongs in. The values are returned in *BITSTART and *BITEND. - If the access does not need to be restricted 0 is returned in + belongs. The values are returned in *BITSTART and *BITEND. *BITPOS + and *OFFSET may be adjusted in the process. + + If the access does not need to be restricted, 0 is returned in both *BITSTART and *BITEND. */ static void get_bit_range (unsigned HOST_WIDE_INT *bitstart, unsigned HOST_WIDE_INT *bitend, tree exp, - HOST_WIDE_INT bitpos) + HOST_WIDE_INT *bitpos, + tree *offset) { - unsigned HOST_WIDE_INT bitoffset; + HOST_WIDE_INT bitoffset; tree field, repr; gcc_assert (TREE_CODE (exp) == COMPONENT_REF); @@ -4490,7 +4493,25 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart, bitoffset += (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1) - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1)); - *bitstart = bitpos - bitoffset; + /* If the adjustment is larger than bitpos, we would have a negative bit + position for the lower bound and this may wreak havoc later. This can + occur only if we have a non-null offset, so adjust offset and bitpos + to make the lower bound non-negative. */ + if (bitoffset > *bitpos) + { + HOST_WIDE_INT adjust = bitoffset - *bitpos; + + gcc_assert ((adjust % BITS_PER_UNIT) == 0); + gcc_assert (*offset != NULL_TREE); + + *bitpos += adjust; + *offset + = size_binop (MINUS_EXPR, *offset, size_int (adjust / BITS_PER_UNIT)); + *bitstart = 0; + } + else + *bitstart = *bitpos - bitoffset; + *bitend = *bitstart + tree_low_cst (DECL_SIZE (repr), 1) - 1; } @@ -4595,7 +4616,7 @@ expand_assignment (tree to, tree from, bool nontemporal) if (TREE_CODE (to) == COMPONENT_REF && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1))) - get_bit_range (&bitregion_start, &bitregion_end, to, bitpos); + get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset); /* If we are going to use store_bit_field and extract_bit_field, make sure to_rtx will be safe for multiple use. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c757d42d..ca5c35a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-04-03 Eric Botcazou + + * gnat.dg/pack18.adb: New test. + * gnat.dg/pack18_pkg.ads: New helper. + 2012-04-03 Richard Guenther PR tree-optimization/52808 diff --git a/gcc/testsuite/gnat.dg/pack18.adb b/gcc/testsuite/gnat.dg/pack18.adb new file mode 100644 index 0000000..857a6f9 --- /dev/null +++ b/gcc/testsuite/gnat.dg/pack18.adb @@ -0,0 +1,12 @@ +-- { dg-do run } + +with Pack18_Pkg; use Pack18_Pkg; + +procedure Pack18 is + use Pack18_Pkg.Attributes_Tables; + Table : Instance; +begin + Init (Table); + Set_Last (Table, 1); + Table.Table (Last (Table)).N := 0; +end; diff --git a/gcc/testsuite/gnat.dg/pack18_pkg.ads b/gcc/testsuite/gnat.dg/pack18_pkg.ads new file mode 100644 index 0000000..2b63fba --- /dev/null +++ b/gcc/testsuite/gnat.dg/pack18_pkg.ads @@ -0,0 +1,21 @@ +with GNAT.Dynamic_Tables; + +package Pack18_Pkg is + + type String_Access is access String; + + type Rec is record + S : String_Access; + B : Boolean; + N : Natural; + end record; + pragma Pack (Rec); + + package Attributes_Tables is new GNAT.Dynamic_Tables + (Table_Component_Type => Rec, + Table_Index_Type => Natural, + Table_Low_Bound => 1, + Table_Initial => 200, + Table_Increment => 200); + +end Pack18_Pkg; -- 2.7.4