stor-layout.c (finish_bitfield_representative): Fallback to conservative maximum...
authorRichard Guenther <rguenther@suse.de>
Tue, 20 Mar 2012 09:31:40 +0000 (09:31 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 20 Mar 2012 09:31:40 +0000 (09:31 +0000)
2012-03-20  Richard Guenther  <rguenther@suse.de>

* 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.

From-SVN: r185563

gcc/ChangeLog
gcc/expr.c
gcc/stor-layout.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/pack16.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/pack16_pkg.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/specs/pack8.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/specs/pack8_pkg.ads [new file with mode: 0644]

index bf9d56f6a8d86b8777a7bddf895a1ea88932d1cc..9eade87ce520c6ea53dfad63f0ce11243839da3b 100644 (file)
@@ -1,3 +1,15 @@
+2012-03-20  Richard Guenther  <rguenther@suse.de>
+
+       * 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  <gingold@adacore.com>
 
        * tree.h (enum size_type_kind): Add stk_ prefix to constants,
index fcd5b36f94a8aae7ba6c7f5b85231b7f97da0382..f9de9080d8b1135c7b6d35ccc9d582647627db25 100644 (file)
@@ -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;
index 2d3f92e202f9cc909b378805b61c34244a92bf47..d79be1424e3d94a036a983aadbe46c8b0eb4a43d 100644 (file)
@@ -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;
index ab0dd1d06bc100f3197c3b7c61d090924e1593c5..02641707476b924350f02f267204c9128dada158 100644 (file)
@@ -1,3 +1,10 @@
+2012-03-20  Richard Guenther  <rguenther@suse.de>
+
+       * 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  <paolo.carlini@oracle.com>
 
        * 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 (file)
index 0000000..eb8e2f9
--- /dev/null
@@ -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 (file)
index 0000000..92884f3
--- /dev/null
@@ -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 (file)
index 0000000..db839cb
--- /dev/null
@@ -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 (file)
index 0000000..f35e629
--- /dev/null
@@ -0,0 +1,5 @@
+package Pack8_Pkg is
+
+   N : Natural := 1;
+
+end Pack8_Pkg;