decl.c (promote_object_alignment): New function taken from...

* 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: r251932
This commit is contained in:
Eric Botcazou 2017-09-09 12:30:42 +00:00 committed by Eric Botcazou
parent 5d5372468c
commit 1dbe491929
4 changed files with 103 additions and 40 deletions

View 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

View File

@ -229,6 +229,7 @@ static vec<variant_desc> build_variant_list (tree,
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> );
@ -850,45 +851,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.
@ -7118,7 +7081,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)))
{
@ -8792,6 +8763,53 @@ validate_alignment (Uint alignment, Entity_Id gnat_entity, unsigned int align)
return align;
}
/* 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;
}
/* 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. */

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

View File

@ -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;