Commit 89ec98ed by Eric Botcazou Committed by Eric Botcazou

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: r251931
parent 7f46ecf6
2017-09-09 Eric Botcazou <ebotcazou@adacore.com> 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 * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Variable>: Apply the
promotion to static memory earlier in the processing. promotion to static memory earlier in the processing.
......
...@@ -230,6 +230,7 @@ static vec<variant_desc> build_variant_list (tree, vec<subst_pair>, ...@@ -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 tree validate_size (Uint, tree, Entity_Id, enum tree_code, bool, bool);
static void set_rm_size (Uint, tree, Entity_Id); static void set_rm_size (Uint, tree, Entity_Id);
static unsigned int validate_alignment (Uint, Entity_Id, unsigned int); 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 void check_ok_for_atomic_type (tree, Entity_Id, bool);
static tree create_field_decl_from (tree, tree, tree, tree, tree, static tree create_field_decl_from (tree, tree, tree, tree, tree,
vec<subst_pair>); vec<subst_pair>);
...@@ -856,45 +857,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) ...@@ -856,45 +857,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
&& No (Renamed_Object (gnat_entity)) && No (Renamed_Object (gnat_entity))
&& No (Address_Clause (gnat_entity)))) && No (Address_Clause (gnat_entity))))
&& TREE_CODE (TYPE_SIZE (gnu_type)) == INTEGER_CST) && TREE_CODE (TYPE_SIZE (gnu_type)) == INTEGER_CST)
{ align = promote_object_alignment (gnu_type, gnat_entity);
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
}
/* If the object is set to have atomic components, find the component /* If the object is set to have atomic components, find the component
type and validate it. type and validate it.
...@@ -6891,7 +6854,15 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed, ...@@ -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)) 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))) if (Present (Component_Clause (gnat_field)))
{ {
...@@ -8808,6 +8779,53 @@ validate_alignment (Uint alignment, Entity_Id gnat_entity, unsigned int align) ...@@ -8808,6 +8779,53 @@ validate_alignment (Uint alignment, Entity_Id gnat_entity, unsigned int align)
return 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 /* 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 an error for GNAT_ENTITY. COMPONENT_P is true if we are being called to
process a component type. */ process a component type. */
......
2017-09-09 Eric Botcazou <ebotcazou@adacore.com> 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... * gnat.dg/specs/vfa.ads: Rename into...
* gnat.dg/specs/vfa1.ads: ...this. * gnat.dg/specs/vfa1.ads: ...this.
* gnat.dg/specs/vfa2.ads: New test. * gnat.dg/specs/vfa2.ads: New test.
......
-- { 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;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment