Commit 0c2837b5 by Eric Botcazou Committed by Eric Botcazou

gigi.h (aggregate_type_contains_array_p): Declare.

	* gcc-interface/gigi.h (aggregate_type_contains_array_p): Declare.
	* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Record_Type>: For an
	extension, test Has_Record_Rep_Clause instead of Has_Specified_Layout.
	(adjust_packed): Return 0 if the type of the field is an aggregate
	type that contains (or is) a self-referential array.
	(type_has_variable_size): Delete.
	* gcc-interface/utils.c (inish_record_type): Constify a variable.
	(aggregate_type_contains_array_p): Add parameter SELF_REFERENTIAL.
	<RECORD_TYPE>: Pass it in the recursive call.
	<ARRAY_TYPE>: If it is true, return true only if the array type is
	self-referential.
	(create_field_decl): Streamline the setting of the alignment on the
	field.  Pass false to aggregate_type_contains_array_p.

From-SVN: r275196
parent c85dbadc
2019-08-30 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/gigi.h (aggregate_type_contains_array_p): Declare.
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Record_Type>: For an
extension, test Has_Record_Rep_Clause instead of Has_Specified_Layout.
(adjust_packed): Return 0 if the type of the field is an aggregate
type that contains (or is) a self-referential array.
(type_has_variable_size): Delete.
* gcc-interface/utils.c (inish_record_type): Constify a variable.
(aggregate_type_contains_array_p): Add parameter SELF_REFERENTIAL.
<RECORD_TYPE>: Pass it in the recursive call.
<ARRAY_TYPE>: If it is true, return true only if the array type is
self-referential.
(create_field_decl): Streamline the setting of the alignment on the
field. Pass false to aggregate_type_contains_array_p.
2019-08-30 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/trans.c (lvalue_required_p) <N_Slice>: Adjust GNU_TYPE
in the recursive call.
<N_Selected_Component>: Likewise.
......
......@@ -202,7 +202,6 @@ static void prepend_one_attribute_pragma (struct attrib **, Node_Id);
static void prepend_attributes (struct attrib **, Entity_Id);
static tree elaborate_expression (Node_Id, Entity_Id, const char *, bool, bool,
bool);
static bool type_has_variable_size (tree);
static tree elaborate_expression_1 (tree, Entity_Id, const char *, bool, bool);
static tree elaborate_expression_2 (tree, Entity_Id, const char *, bool, bool,
unsigned int);
......@@ -2953,10 +2952,13 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
: 0;
const bool has_align = Known_Alignment (gnat_entity);
const bool has_discr = Has_Discriminants (gnat_entity);
const bool has_rep = Has_Specified_Layout (gnat_entity);
const bool is_extension
= (Is_Tagged_Type (gnat_entity)
&& Nkind (record_definition) == N_Derived_Type_Definition);
const bool has_rep
= is_extension
? Has_Record_Rep_Clause (gnat_entity)
: Has_Specified_Layout (gnat_entity);
const bool is_unchecked_union = Is_Unchecked_Union (gnat_entity);
bool all_rep = has_rep;
......@@ -6865,11 +6867,13 @@ choices_to_gnu (tree gnu_operand, Node_Id gnat_choices)
static int
adjust_packed (tree field_type, tree record_type, int packed)
{
/* If the field contains an item of variable size, we cannot pack it
because we cannot create temporaries of non-fixed size in case
we need to take the address of the field. See addressable_p and
the notes on the addressability issues for further details. */
if (type_has_variable_size (field_type))
/* If the field contains an array with self-referential size, we'd better
not pack it because this would misalign it and, therefore, cause large
temporaries to be created in case we need to take the address of the
field. See addressable_p and the notes on the addressability issues
for further details. */
if (AGGREGATE_TYPE_P (field_type)
&& aggregate_type_contains_array_p (field_type, true))
return 0;
/* In the other cases, we can honor the packing. */
......@@ -7274,31 +7278,6 @@ components_need_strict_alignment (Node_Id component_list)
return false;
}
/* Return true if TYPE is a type with variable size or a padding type with a
field of variable size or a record that has a field with such a type. */
static bool
type_has_variable_size (tree type)
{
tree field;
if (!TREE_CONSTANT (TYPE_SIZE (type)))
return true;
if (TYPE_IS_PADDING_P (type)
&& !TREE_CONSTANT (DECL_SIZE (TYPE_FIELDS (type))))
return true;
if (!RECORD_OR_UNION_TYPE_P (type))
return false;
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (type_has_variable_size (TREE_TYPE (field)))
return true;
return false;
}
/* Return true if FIELD is an artificial field. */
static bool
......
......@@ -835,6 +835,11 @@ extern tree get_base_type (tree type);
in bits. If we don't know anything about the alignment, return 0. */
extern unsigned int known_alignment (tree exp);
/* Return true if TYPE, an aggregate type, contains (or is) an array.
If SELF_REFERENTIAL is true, then an additional requirement on the
array is that it be self-referential. */
extern bool aggregate_type_contains_array_p (tree type, bool self_referential);
/* Return true if VALUE is a multiple of FACTOR. FACTOR must be a power
of 2. */
extern bool value_factor_p (tree value, unsigned HOST_WIDE_INT factor);
......
......@@ -1948,7 +1948,7 @@ finish_record_type (tree record_type, tree field_list, int rep_level,
if (DECL_BIT_FIELD (field)
&& operand_equal_p (this_size, TYPE_SIZE (type), 0))
{
unsigned int align = TYPE_ALIGN (type);
const unsigned int align = TYPE_ALIGN (type);
/* In the general case, type alignment is required. */
if (value_factor_p (pos, align))
......@@ -2764,10 +2764,12 @@ create_var_decl (tree name, tree asm_name, tree type, tree init,
return var_decl;
}
/* Return true if TYPE, an aggregate type, contains (or is) an array. */
/* Return true if TYPE, an aggregate type, contains (or is) an array.
If SELF_REFERENTIAL is true, then an additional requirement on the
array is that it be self-referential. */
static bool
aggregate_type_contains_array_p (tree type)
bool
aggregate_type_contains_array_p (tree type, bool self_referential)
{
switch (TREE_CODE (type))
{
......@@ -2778,13 +2780,14 @@ aggregate_type_contains_array_p (tree type)
tree field;
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (AGGREGATE_TYPE_P (TREE_TYPE (field))
&& aggregate_type_contains_array_p (TREE_TYPE (field)))
&& aggregate_type_contains_array_p (TREE_TYPE (field),
self_referential))
return true;
return false;
}
case ARRAY_TYPE:
return true;
return self_referential ? type_contains_placeholder_p (type) : true;
default:
gcc_unreachable ();
......@@ -2808,18 +2811,6 @@ create_field_decl (tree name, tree type, tree record_type, tree size, tree pos,
DECL_CONTEXT (field_decl) = record_type;
TREE_READONLY (field_decl) = TYPE_READONLY (type);
/* If FIELD_TYPE is BLKmode, we must ensure this is aligned to at least a
byte boundary since GCC cannot handle less-aligned BLKmode bitfields.
Likewise for an aggregate without specified position that contains an
array, because in this case slices of variable length of this array
must be handled by GCC and variable-sized objects need to be aligned
to at least a byte boundary. */
if (packed && (TYPE_MODE (type) == BLKmode
|| (!pos
&& AGGREGATE_TYPE_P (type)
&& aggregate_type_contains_array_p (type))))
SET_DECL_ALIGN (field_decl, BITS_PER_UNIT);
/* If a size is specified, use it. Otherwise, if the record type is packed
compute a size to use, which may differ from the object's natural size.
We always set a size in this case to trigger the checks for bitfield
......@@ -2872,23 +2863,39 @@ create_field_decl (tree name, tree type, tree record_type, tree size, tree pos,
DECL_PACKED (field_decl) = pos ? DECL_BIT_FIELD (field_decl) : packed;
/* If FIELD_TYPE is BLKmode, we must ensure this is aligned to at least a
byte boundary since GCC cannot handle less-aligned BLKmode bitfields.
Likewise for an aggregate without specified position that contains an
array, because in this case slices of variable length of this array
must be handled by GCC and variable-sized objects need to be aligned
to at least a byte boundary. */
if (packed && (TYPE_MODE (type) == BLKmode
|| (!pos
&& AGGREGATE_TYPE_P (type)
&& aggregate_type_contains_array_p (type, false))))
SET_DECL_ALIGN (field_decl, BITS_PER_UNIT);
/* Bump the alignment if need be, either for bitfield/packing purposes or
to satisfy the type requirements if no such consideration applies. When
to satisfy the type requirements if no such considerations apply. When
we get the alignment from the type, indicate if this is from an explicit
user request, which prevents stor-layout from lowering it later on. */
{
unsigned int bit_align
= (DECL_BIT_FIELD (field_decl) ? 1
: packed && TYPE_MODE (type) != BLKmode ? BITS_PER_UNIT : 0);
else
{
const unsigned int field_align
= DECL_BIT_FIELD (field_decl)
? 1
: packed
? BITS_PER_UNIT
: 0;
if (bit_align > DECL_ALIGN (field_decl))
SET_DECL_ALIGN (field_decl, bit_align);
else if (!bit_align && TYPE_ALIGN (type) > DECL_ALIGN (field_decl))
{
SET_DECL_ALIGN (field_decl, TYPE_ALIGN (type));
DECL_USER_ALIGN (field_decl) = TYPE_USER_ALIGN (type);
}
}
if (field_align > DECL_ALIGN (field_decl))
SET_DECL_ALIGN (field_decl, field_align);
else if (!field_align && TYPE_ALIGN (type) > DECL_ALIGN (field_decl))
{
SET_DECL_ALIGN (field_decl, TYPE_ALIGN (type));
DECL_USER_ALIGN (field_decl) = TYPE_USER_ALIGN (type);
}
}
if (pos)
{
......
2019-08-30 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/pack24.adb: New test.
2019-08-30 Jeff Law <law@redhat.com>
* gcc.target/mips/r10k-cache-barrier-9.c: Suppress warnings.
......
-- { dg-do run }
with Interfaces;
procedure Pack24 is
type Enum_1 is (Lit_1);
for Enum_1'SIZE use 16;
type Rec1(D1 : Enum_1 := Lit_1) is
record
case D1 is
when Lit_1 =>
F1 : Interfaces.Unsigned_16;
when others =>
Null;
end case;
end record;
pragma Pack(Rec1);
type Rec2 is
record
F1 : Interfaces.Unsigned_16;
F2 : Rec1;
end record;
pragma Pack(Rec2);
type Rec3 is record
F1 : Interfaces.Unsigned_8;
F2 : Rec2;
end record;
pragma Pack(Rec3);
begin
if Rec3'Size /= 56 then
raise Program_Error;
end if;
end;
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