From 89ec98ed7ecf0a52175726cca867d471fcad9811 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Sat, 9 Sep 2017 12:29:08 +0000 Subject: [PATCH] decl.c (promote_object_alignment): New function taken from... * gcc-interface/decl.c (promote_object_alignment): New function taken from... (gnat_to_gnu_entity) : ...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 | 8 +++ gcc/ada/gcc-interface/decl.c | 98 +++++++++++++++++++-------------- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gnat.dg/specs/atomic3.ads | 33 +++++++++++ 4 files changed, 103 insertions(+), 40 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/specs/atomic3.ads diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 2c906b9..d0d230c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,13 @@ 2017-09-09 Eric Botcazou + * gcc-interface/decl.c (promote_object_alignment): New function taken + from... + (gnat_to_gnu_entity) : ...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 + * gcc-interface/decl.c (gnat_to_gnu_entity) : Apply the promotion to static memory earlier in the processing. diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 0798a8f..2a31e8f 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -230,6 +230,7 @@ static vec build_variant_list (tree, vec, 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); @@ -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; } +/* 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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 928a1e4..0f58fb7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2017-09-09 Eric Botcazou + * gnat.dg/specs/atomic3.ads: New test. + +2017-09-09 Eric Botcazou + * gnat.dg/specs/vfa.ads: Rename into... * gnat.dg/specs/vfa1.ads: ...this. * gnat.dg/specs/vfa2.ads: New test. diff --git a/gcc/testsuite/gnat.dg/specs/atomic3.ads b/gcc/testsuite/gnat.dg/specs/atomic3.ads new file mode 100644 index 0000000..875f223 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/atomic3.ads @@ -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; -- 2.7.4