diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2008-03-08 11:30:26 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2008-03-08 11:30:26 +0000 |
commit | 8853cb0bcdbbf5424ceeed44778e302c4249532b (patch) | |
tree | 6c1f733a1df630a5933cb80960a1e3724216b3f3 /gcc | |
parent | 66abe22c0716119ac01164cebd147d86a0ed8c70 (diff) | |
download | gcc-8853cb0bcdbbf5424ceeed44778e302c4249532b.zip gcc-8853cb0bcdbbf5424ceeed44778e302c4249532b.tar.gz gcc-8853cb0bcdbbf5424ceeed44778e302c4249532b.tar.bz2 |
utils.c (finish_record_type): Clear DECL_BIT_FIELD on sufficiently aligned bit-fields...
* utils.c (finish_record_type): Clear DECL_BIT_FIELD on sufficiently
aligned bit-fields, bumping the alignment of the record type if deemed
profitable.
(value_factor_p): Return false instead of 0.
From-SVN: r133028
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ada/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/ada/utils.c | 54 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/pack4.adb | 38 |
4 files changed, 93 insertions, 10 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 2a10f10..77ceeda 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,12 @@ 2008-03-08 Eric Botcazou <ebotcazou@adacore.com> + * utils.c (finish_record_type): Clear DECL_BIT_FIELD on sufficiently + aligned bit-fields, bumping the alignment of the record type if deemed + profitable. + (value_factor_p): Return false instead of 0. + +2008-03-08 Eric Botcazou <ebotcazou@adacore.com> + * decl.c (gnat_to_gnu_entity) <E_Signed_Integer_Subtype>: Add support for scalar types with small alignment. diff --git a/gcc/ada/utils.c b/gcc/ada/utils.c index 46ce865..f1ffa4f 100644 --- a/gcc/ada/utils.c +++ b/gcc/ada/utils.c @@ -752,6 +752,7 @@ finish_record_type (tree record_type, tree fieldlist, int rep_level, tree size = bitsize_zero_node; bool had_size = TYPE_SIZE (record_type) != 0; bool had_size_unit = TYPE_SIZE_UNIT (record_type) != 0; + bool had_align = TYPE_ALIGN (record_type) != 0; tree field; if (name && TREE_CODE (name) == TYPE_DECL) @@ -804,24 +805,55 @@ finish_record_type (tree record_type, tree fieldlist, int rep_level, for (field = fieldlist; field; field = TREE_CHAIN (field)) { - tree pos = bit_position (field); - tree type = TREE_TYPE (field); + tree pos = bit_position (field); tree this_size = DECL_SIZE (field); - tree this_ada_size = DECL_SIZE (field); + tree this_ada_size; - if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE - || TREE_CODE (type) == QUAL_UNION_TYPE) + if ((TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE + || TREE_CODE (type) == QUAL_UNION_TYPE) && !TYPE_IS_FAT_POINTER_P (type) && !TYPE_CONTAINS_TEMPLATE_P (type) && TYPE_ADA_SIZE (type)) this_ada_size = TYPE_ADA_SIZE (type); + else + this_ada_size = this_size; /* Clear DECL_BIT_FIELD for the cases layout_decl does not handle. */ - if (DECL_BIT_FIELD (field) && !STRICT_ALIGNMENT - && value_factor_p (pos, BITS_PER_UNIT) + if (DECL_BIT_FIELD (field) && operand_equal_p (this_size, TYPE_SIZE (type), 0)) - DECL_BIT_FIELD (field) = 0; + { + unsigned int align = TYPE_ALIGN (type); + + /* In the general case, type alignment is required. */ + if (value_factor_p (pos, align)) + { + /* The enclosing record type must be sufficiently aligned. + Otherwise, if no alignment was specified for it and it + has been laid out already, bump its alignment to the + desired one if this is compatible with its size. */ + if (TYPE_ALIGN (record_type) >= align) + { + DECL_ALIGN (field) = MAX (DECL_ALIGN (field), align); + DECL_BIT_FIELD (field) = 0; + } + else if (!had_align + && rep_level == 0 + && value_factor_p (TYPE_SIZE (record_type), align)) + { + TYPE_ALIGN (record_type) = align; + DECL_ALIGN (field) = MAX (DECL_ALIGN (field), align); + DECL_BIT_FIELD (field) = 0; + } + } + + /* In the non-strict alignment case, only byte alignment is. */ + if (!STRICT_ALIGNMENT + && DECL_BIT_FIELD (field) + && value_factor_p (pos, BITS_PER_UNIT)) + DECL_BIT_FIELD (field) = 0; + } /* If we still have DECL_BIT_FIELD set at this point, we know the field is technically not addressable. Except that it can actually be @@ -830,7 +862,9 @@ finish_record_type (tree record_type, tree fieldlist, int rep_level, DECL_NONADDRESSABLE_P (field) |= DECL_BIT_FIELD (field) && DECL_MODE (field) != BLKmode; - if ((rep_level > 0) && !DECL_BIT_FIELD (field)) + /* A type must be as aligned as its most aligned field that is not + a bit-field. But this is already enforced by layout_type. */ + if (rep_level > 0 && !DECL_BIT_FIELD (field)) TYPE_ALIGN (record_type) = MAX (TYPE_ALIGN (record_type), DECL_ALIGN (field)); @@ -1800,7 +1834,7 @@ value_factor_p (tree value, HOST_WIDE_INT factor) return (value_factor_p (TREE_OPERAND (value, 0), factor) || value_factor_p (TREE_OPERAND (value, 1), factor)); - return 0; + return false; } /* Given 2 consecutive field decls PREV_FIELD and CURR_FIELD, return true diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 64896b8..4915a42 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2008-03-08 Eric Botcazou <ebotcazou@adacore.com> + * gnat.dg/pack4.adb: New test. + +2008-03-08 Eric Botcazou <ebotcazou@adacore.com> + * gnat.dg/small_alignment.adb: New test. 2008-03-07 Eric Botcazou <ebotcazou@adacore.com> diff --git a/gcc/testsuite/gnat.dg/pack4.adb b/gcc/testsuite/gnat.dg/pack4.adb new file mode 100644 index 0000000..2c73e1d --- /dev/null +++ b/gcc/testsuite/gnat.dg/pack4.adb @@ -0,0 +1,38 @@ +-- { dg-do run } + +procedure Pack4 is + + type Time_T is record + Hour : Integer; + end record; + + type Date_And_Time_T is record + Date : Integer; + Time : Time_T; + end record; + + pragma Pack(Date_And_Time_T); + + procedure + Assign_Hour_Of (T : out Time_T) + is + begin + T.Hour := 44; + end; + + procedure + Clobber_Hour_Of (DT: out Date_And_Time_T) + is + begin + Assign_Hour_Of (Dt.Time); + end; + + DT : Date_And_Time_T; + +begin + DT.Time.Hour := 22; + Clobber_Hour_Of (DT); + if DT.Time.Hour /= 44 then + raise Program_Error; + end if; +end; |