From fa42e1a454c4d18a219486c7e0878ce51265456a Mon Sep 17 00:00:00 2001 From: rguenth Date: Tue, 20 Mar 2012 09:31:40 +0000 Subject: [PATCH] 2012-03-20 Richard Guenther * stor-layout.c (finish_bitfield_representative): Fallback to conservative maximum size if the padding up to the next field cannot be computed as a constant. (finish_bitfield_layout): If we cannot compute the distance between the start of the bitfield representative and the bitfield member start a new representative. * expr.c (get_bit_range): The distance between the start of the bitfield representative and the bitfield member is zero if the field offsets are not constants. * gnat.dg/pack16.adb: New testcase. * gnat.dg/pack16_pkg.ads: Likewise. * gnat.dg/specs/pack8.ads: Likewise. * gnat.dg/specs/pack8_pkg.ads: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@185563 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 12 +++++++++++ gcc/expr.c | 19 ++++++++++------- gcc/stor-layout.c | 35 +++++++++++++++++++++++++++---- gcc/testsuite/ChangeLog | 7 +++++++ gcc/testsuite/gnat.dg/pack16.adb | 26 +++++++++++++++++++++++ gcc/testsuite/gnat.dg/pack16_pkg.ads | 5 +++++ gcc/testsuite/gnat.dg/specs/pack8.ads | 19 +++++++++++++++++ gcc/testsuite/gnat.dg/specs/pack8_pkg.ads | 5 +++++ 8 files changed, 117 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/pack16.adb create mode 100644 gcc/testsuite/gnat.dg/pack16_pkg.ads create mode 100644 gcc/testsuite/gnat.dg/specs/pack8.ads create mode 100644 gcc/testsuite/gnat.dg/specs/pack8_pkg.ads diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bf9d56f..9eade87 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2012-03-20 Richard Guenther + + * stor-layout.c (finish_bitfield_representative): Fallback + to conservative maximum size if the padding up to the next + field cannot be computed as a constant. + (finish_bitfield_layout): If we cannot compute the distance + between the start of the bitfield representative and the + bitfield member start a new representative. + * expr.c (get_bit_range): The distance between the start of + the bitfield representative and the bitfield member is zero + if the field offsets are not constants. + 2012-03-20 Tristan Gingold * tree.h (enum size_type_kind): Add stk_ prefix to constants, diff --git a/gcc/expr.c b/gcc/expr.c index fcd5b36..f9de908 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -4452,7 +4452,7 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart, HOST_WIDE_INT bitpos) { unsigned HOST_WIDE_INT bitoffset; - tree field, repr, offset; + tree field, repr; gcc_assert (TREE_CODE (exp) == COMPONENT_REF); @@ -4467,12 +4467,17 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart, } /* Compute the adjustment to bitpos from the offset of the field - relative to the representative. */ - offset = size_diffop (DECL_FIELD_OFFSET (field), - DECL_FIELD_OFFSET (repr)); - bitoffset = (tree_low_cst (offset, 1) * BITS_PER_UNIT - + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1) - - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1)); + relative to the representative. DECL_FIELD_OFFSET of field and + repr are the same by construction if they are not constants, + see finish_bitfield_layout. */ + if (host_integerp (DECL_FIELD_OFFSET (field), 1) + && host_integerp (DECL_FIELD_OFFSET (repr), 1)) + bitoffset = (tree_low_cst (DECL_FIELD_OFFSET (field), 1) + - tree_low_cst (DECL_FIELD_OFFSET (repr), 1)) * BITS_PER_UNIT; + else + bitoffset = 0; + bitoffset += (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1) + - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1)); *bitstart = bitpos - bitoffset; *bitend = *bitstart + tree_low_cst (DECL_SIZE (repr), 1) - 1; diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 2d3f92e..d79be14 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -1781,10 +1781,17 @@ finish_bitfield_representative (tree repr, tree field) return; maxsize = size_diffop (DECL_FIELD_OFFSET (nextf), DECL_FIELD_OFFSET (repr)); - gcc_assert (host_integerp (maxsize, 1)); - maxbitsize = (tree_low_cst (maxsize, 1) * BITS_PER_UNIT - + tree_low_cst (DECL_FIELD_BIT_OFFSET (nextf), 1) - - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1)); + if (host_integerp (maxsize, 1)) + { + maxbitsize = (tree_low_cst (maxsize, 1) * BITS_PER_UNIT + + tree_low_cst (DECL_FIELD_BIT_OFFSET (nextf), 1) + - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1)); + /* If the group ends within a bitfield nextf does not need to be + aligned to BITS_PER_UNIT. Thus round up. */ + maxbitsize = (maxbitsize + BITS_PER_UNIT - 1) & ~(BITS_PER_UNIT - 1); + } + else + maxbitsize = bitsize; } else { @@ -1888,6 +1895,8 @@ finish_bitfield_layout (record_layout_info rli) } else if (DECL_BIT_FIELD_TYPE (field)) { + gcc_assert (repr != NULL_TREE); + /* Zero-size bitfields finish off a representative and do not have a representative themselves. This is required by the C++ memory model. */ @@ -1896,6 +1905,24 @@ finish_bitfield_layout (record_layout_info rli) finish_bitfield_representative (repr, prev); repr = NULL_TREE; } + + /* We assume that either DECL_FIELD_OFFSET of the representative + and each bitfield member is a constant or they are equal. + This is because we need to be able to compute the bit-offset + of each field relative to the representative in get_bit_range + during RTL expansion. + If these constraints are not met, simply force a new + representative to be generated. That will at most + generate worse code but still maintain correctness with + respect to the C++ memory model. */ + else if (!((host_integerp (DECL_FIELD_OFFSET (repr), 1) + && host_integerp (DECL_FIELD_OFFSET (field), 1)) + || operand_equal_p (DECL_FIELD_OFFSET (repr), + DECL_FIELD_OFFSET (field), 0))) + { + finish_bitfield_representative (repr, prev); + repr = start_bitfield_representative (field); + } } else continue; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ab0dd1d..0264170 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2012-03-20 Richard Guenther + + * gnat.dg/pack16.adb: New testcase. + * gnat.dg/pack16_pkg.ads: Likewise. + * gnat.dg/specs/pack8.ads: Likewise. + * gnat.dg/specs/pack8_pkg.ads: Likewise. + 2012-03-19 Paolo Carlini * g++.dg/warn/Wuseless-cast.C: Extend. diff --git a/gcc/testsuite/gnat.dg/pack16.adb b/gcc/testsuite/gnat.dg/pack16.adb new file mode 100644 index 0000000..eb8e2f9 --- /dev/null +++ b/gcc/testsuite/gnat.dg/pack16.adb @@ -0,0 +1,26 @@ +-- { dg-do compile } +-- { dg-options "-gnatws" } + +with Pack16_Pkg; use Pack16_Pkg; + +procedure Pack16 is + + type Sample_Table_T is array (1 .. N) of Integer; + + type Clock_T is record + N_Ticks : Integer := 0; + end record; + + type Sampling_Descriptor_T is record + Values : Sample_Table_T; + Valid : Boolean; + Tstamp : Clock_T; + end record; + + pragma Pack (Sampling_Descriptor_T); + + Sampling_Data : Sampling_Descriptor_T; + +begin + null; +end; diff --git a/gcc/testsuite/gnat.dg/pack16_pkg.ads b/gcc/testsuite/gnat.dg/pack16_pkg.ads new file mode 100644 index 0000000..92884f3 --- /dev/null +++ b/gcc/testsuite/gnat.dg/pack16_pkg.ads @@ -0,0 +1,5 @@ +package Pack16_Pkg is + + N : Natural := 16; + +end Pack16_Pkg; diff --git a/gcc/testsuite/gnat.dg/specs/pack8.ads b/gcc/testsuite/gnat.dg/specs/pack8.ads new file mode 100644 index 0000000..db839cb --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/pack8.ads @@ -0,0 +1,19 @@ +with Pack8_Pkg; + +package Pack8 is + + subtype Index_Type is Integer range 1 .. Pack8_Pkg.N; + + subtype Str is String( Index_Type); + + subtype Str2 is String (1 .. 11); + + type Rec is record + S1 : Str; + S2 : Str; + B : Boolean; + S3 : Str2; + end record; + pragma Pack (Rec); + +end Pack8; diff --git a/gcc/testsuite/gnat.dg/specs/pack8_pkg.ads b/gcc/testsuite/gnat.dg/specs/pack8_pkg.ads new file mode 100644 index 0000000..f35e629 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/pack8_pkg.ads @@ -0,0 +1,5 @@ +package Pack8_Pkg is + + N : Natural := 1; + +end Pack8_Pkg; -- 2.7.4