decl.c (promote_object_alignment): New function taken from...
authorEric Botcazou <ebotcazou@adacore.com>
Sat, 9 Sep 2017 12:29:08 +0000 (12:29 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Sat, 9 Sep 2017 12:29:08 +0000 (12:29 +0000)
* gcc-interface/decl.c (promote_object_alignment): New function taken
from...
(gnat_to_gnu_entity) <E_Variable>: ...here.  Invoke it.
(gnat_to_gnu_field): If the field is Atomic or VFA, invoke it and
create a padding type on success before doing the atomic check.

From-SVN: r251931

gcc/ada/ChangeLog
gcc/ada/gcc-interface/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/specs/atomic3.ads [new file with mode: 0644]

index 2c906b9b9e78feff8934a0c91664020249ca6e29..d0d230c167a9946472e5483c3ccd8daa5090a27a 100644 (file)
@@ -1,3 +1,11 @@
+2017-09-09  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc-interface/decl.c (promote_object_alignment): New function taken
+       from...
+       (gnat_to_gnu_entity) <E_Variable>: ...here.  Invoke it.
+       (gnat_to_gnu_field): If the field is Atomic or VFA, invoke it and
+       create a padding type on success before doing the atomic check.
+
 2017-09-09  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Variable>: Apply the
index 0798a8f2da412ddcc7a60dd9fa1d13753db055df..2a31e8f917ea05a4a7726deab4b0586ceccd1380 100644 (file)
@@ -230,6 +230,7 @@ static vec<variant_desc> build_variant_list (tree, vec<subst_pair>,
 static tree validate_size (Uint, tree, Entity_Id, enum tree_code, bool, bool);
 static void set_rm_size (Uint, tree, Entity_Id);
 static unsigned int validate_alignment (Uint, Entity_Id, unsigned int);
+static unsigned int promote_object_alignment (tree, Entity_Id);
 static void check_ok_for_atomic_type (tree, Entity_Id, bool);
 static tree create_field_decl_from (tree, tree, tree, tree, tree,
                                    vec<subst_pair>);
@@ -856,45 +857,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
                    && No (Renamed_Object (gnat_entity))
                    && No (Address_Clause (gnat_entity))))
            && TREE_CODE (TYPE_SIZE (gnu_type)) == INTEGER_CST)
-         {
-           unsigned int size_cap, align_cap;
-
-           /* No point in promoting the alignment if this doesn't prevent
-              BLKmode access to the object, in particular block copy, as
-              this will for example disable the NRV optimization for it.
-              No point in jumping through all the hoops needed in order
-              to support BIGGEST_ALIGNMENT if we don't really have to.
-              So we cap to the smallest alignment that corresponds to
-              a known efficient memory access pattern of the target.  */
-           if (Is_Atomic_Or_VFA (gnat_entity))
-             {
-               size_cap = UINT_MAX;
-               align_cap = BIGGEST_ALIGNMENT;
-             }
-           else
-             {
-               size_cap = MAX_FIXED_MODE_SIZE;
-               align_cap = get_mode_alignment (ptr_mode);
-             }
-
-           if (!tree_fits_uhwi_p (TYPE_SIZE (gnu_type))
-               || compare_tree_int (TYPE_SIZE (gnu_type), size_cap) > 0)
-             align = 0;
-           else if (compare_tree_int (TYPE_SIZE (gnu_type), align_cap) > 0)
-             align = align_cap;
-           else
-             align = ceil_pow2 (tree_to_uhwi (TYPE_SIZE (gnu_type)));
-
-           /* But make sure not to under-align the object.  */
-           if (align <= TYPE_ALIGN (gnu_type))
-             align = 0;
-
-           /* And honor the minimum valid atomic alignment, if any.  */
-#ifdef MINIMUM_ATOMIC_ALIGNMENT
-           else if (align < MINIMUM_ATOMIC_ALIGNMENT)
-             align = MINIMUM_ATOMIC_ALIGNMENT;
-#endif
-         }
+         align = promote_object_alignment (gnu_type, gnat_entity);
 
        /* If the object is set to have atomic components, find the component
           type and validate it.
@@ -6891,7 +6854,15 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
     }
 
   if (Is_Atomic_Or_VFA (gnat_field))
-    check_ok_for_atomic_type (gnu_field_type, gnat_field, false);
+    {
+      const unsigned int align
+       = promote_object_alignment (gnu_field_type, gnat_field);
+      if (align > 0)
+       gnu_field_type
+         = maybe_pad_type (gnu_field_type, NULL_TREE, align, gnat_field,
+                           false, false, definition, true);
+      check_ok_for_atomic_type (gnu_field_type, gnat_field, false);
+    }
 
   if (Present (Component_Clause (gnat_field)))
     {
@@ -8808,6 +8779,53 @@ validate_alignment (Uint alignment, Entity_Id gnat_entity, unsigned int align)
   return align;
 }
 \f
+/* Promote the alignment of GNU_TYPE corresponding to GNAT_ENTITY.  Return
+   a positive value on success or zero on failure.  */
+
+static unsigned int
+promote_object_alignment (tree gnu_type, Entity_Id gnat_entity)
+{
+  unsigned int align, size_cap, align_cap;
+
+  /* No point in promoting the alignment if this doesn't prevent BLKmode access
+     to the object, in particular block copy, as this will for example disable
+     the NRV optimization for it.  No point in jumping through all the hoops
+     needed in order to support BIGGEST_ALIGNMENT if we don't really have to.
+     So we cap to the smallest alignment that corresponds to a known efficient
+     memory access pattern, except for Atomic and Volatile_Full_Access.  */
+  if (Is_Atomic_Or_VFA (gnat_entity))
+    {
+      size_cap = UINT_MAX;
+      align_cap = BIGGEST_ALIGNMENT;
+    }
+  else
+    {
+      size_cap = MAX_FIXED_MODE_SIZE;
+      align_cap = get_mode_alignment (ptr_mode);
+    }
+
+  /* Do the promotion within the above limits.  */
+  if (!tree_fits_uhwi_p (TYPE_SIZE (gnu_type))
+      || compare_tree_int (TYPE_SIZE (gnu_type), size_cap) > 0)
+    align = 0;
+  else if (compare_tree_int (TYPE_SIZE (gnu_type), align_cap) > 0)
+    align = align_cap;
+  else
+    align = ceil_pow2 (tree_to_uhwi (TYPE_SIZE (gnu_type)));
+
+  /* But make sure not to under-align the object.  */
+  if (align <= TYPE_ALIGN (gnu_type))
+    align = 0;
+
+   /* And honor the minimum valid atomic alignment, if any.  */
+#ifdef MINIMUM_ATOMIC_ALIGNMENT
+  else if (align < MINIMUM_ATOMIC_ALIGNMENT)
+    align = MINIMUM_ATOMIC_ALIGNMENT;
+#endif
+
+  return align;
+}
+\f
 /* Verify that TYPE is something we can implement atomically.  If not, issue
    an error for GNAT_ENTITY.  COMPONENT_P is true if we are being called to
    process a component type.  */
index 928a1e42006bc2ce02a0cbd2e383c12d967a01db..0f58fb777f3f3e972599249580bb8d0e5c1db160 100644 (file)
@@ -1,3 +1,7 @@
+2017-09-09  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/specs/atomic3.ads: New test.
+
 2017-09-09  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/specs/vfa.ads: Rename into...
diff --git a/gcc/testsuite/gnat.dg/specs/atomic3.ads b/gcc/testsuite/gnat.dg/specs/atomic3.ads
new file mode 100644 (file)
index 0000000..875f223
--- /dev/null
@@ -0,0 +1,33 @@
+-- { dg-do compile }
+
+package Atomic3 is
+
+   type Four_Bits is mod 2**4;
+   type Fourteen_Bits is mod 2**14;
+   type Twenty_Eight_Bits is mod 2**28;
+
+   type Rec1 (Mode : Boolean := True) is record
+      Reserved : Four_Bits;
+      case Mode is
+         when True =>
+           High_Part : Fourteen_Bits;
+           Low_Part  : Fourteen_Bits;
+         when False =>
+           Data : Twenty_Eight_Bits;
+      end case;
+   end record;
+   for Rec1 use record
+      Reserved  at 0 range 28 .. 31;
+      High_Part at 0 range 14 .. 27;
+      Low_Part  at 0 range  0 .. 13;
+      Data      at 0 range  0 .. 27;
+   end record;
+   for Rec1'Size use 32;
+   pragma Unchecked_Union (Rec1);
+
+   type Rec2 is record
+      A : Rec1;
+      pragma Atomic (A);
+   end record;
+
+end Atomic3;