mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-12 13:23:47 +08:00
decl.c (maybe_pad_type): Try to get a form of the type with integral mode even if...
* decl.c (maybe_pad_type): Try to get a form of the type with integral mode even if the alignment is not a factor of the original size. But make sure to create the inner field with the original size. Reorder. * trans.c (addressable_p) <COMPONENT_REF>: Treat the field of a padding record as always addressable. * utils.c (convert): Deal specially with conversions between original and packable versions of a record type. * utils2.c (build_binary_op) <MODIFY_EXPR>: Be more restrictive when recognizing an assignment between padded objects. From-SVN: r134916
This commit is contained in:
parent
093daf0fc7
commit
88f36b7eb6
@ -1,3 +1,15 @@
|
||||
2008-05-03 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* decl.c (maybe_pad_type): Try to get a form of the type with integral
|
||||
mode even if the alignment is not a factor of the original size. But
|
||||
make sure to create the inner field with the original size. Reorder.
|
||||
* trans.c (addressable_p) <COMPONENT_REF>: Treat the field of a padding
|
||||
record as always addressable.
|
||||
* utils.c (convert): Deal specially with conversions between original
|
||||
and packable versions of a record type.
|
||||
* utils2.c (build_binary_op) <MODIFY_EXPR>: Be more restrictive when
|
||||
recognizing an assignment between padded objects.
|
||||
|
||||
2008-05-01 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* decl.c (make_packable_type): Resize the last component to its RM size
|
||||
|
@ -5448,9 +5448,9 @@ make_packable_type (tree type, bool in_record)
|
||||
|
||||
new_type = make_node (TREE_CODE (type));
|
||||
|
||||
/* Copy the name and flags from the old type to that of the new. Note
|
||||
that we rely on the pointer equality created here for TYPE_NAME at
|
||||
the end of gnat_to_gnu. */
|
||||
/* Copy the name and flags from the old type to that of the new.
|
||||
Note that we rely on the pointer equality created here for
|
||||
TYPE_NAME to look through conversions in various places. */
|
||||
TYPE_NAME (new_type) = TYPE_NAME (type);
|
||||
TYPE_JUSTIFIED_MODULAR_P (new_type) = TYPE_JUSTIFIED_MODULAR_P (type);
|
||||
TYPE_CONTAINS_TEMPLATE_P (new_type) = TYPE_CONTAINS_TEMPLATE_P (type);
|
||||
@ -5576,7 +5576,7 @@ make_packable_type (tree type, bool in_record)
|
||||
GNAT_ENTITY and NAME_TRAILER are used to name the resulting record and
|
||||
to issue a warning.
|
||||
|
||||
IS_USER_TYPE is true if we must be sure we complete the original type.
|
||||
IS_USER_TYPE is true if we must complete the original type.
|
||||
|
||||
DEFINITION is true if this type is being defined.
|
||||
|
||||
@ -5634,16 +5634,7 @@ maybe_pad_type (tree type, tree size, unsigned int align,
|
||||
if (align == 0 && !size)
|
||||
return type;
|
||||
|
||||
/* We used to modify the record in place in some cases, but that could
|
||||
generate incorrect debugging information. So make a new record
|
||||
type and name. */
|
||||
record = make_node (RECORD_TYPE);
|
||||
|
||||
if (Present (gnat_entity))
|
||||
TYPE_NAME (record) = create_concat_name (gnat_entity, name_trailer);
|
||||
|
||||
/* If we were making a type, complete the original type and give it a
|
||||
name. */
|
||||
/* If requested, complete the original type and give it a name. */
|
||||
if (is_user_type)
|
||||
create_type_decl (get_entity_name (gnat_entity), type,
|
||||
NULL, !Comes_From_Source (gnat_entity),
|
||||
@ -5652,41 +5643,56 @@ maybe_pad_type (tree type, tree size, unsigned int align,
|
||||
&& DECL_IGNORED_P (TYPE_NAME (type))),
|
||||
gnat_entity);
|
||||
|
||||
/* If we are changing the alignment and the input type is a record with
|
||||
BLKmode and a small constant size, try to make a form that has an
|
||||
integral mode. That might allow this record to have an integral mode,
|
||||
which will be much more efficient. There is no point in doing this if a
|
||||
size is specified unless it is also smaller than the maximum mode size
|
||||
and it is incorrect to do this if the size of the original type is not a
|
||||
multiple of the alignment. */
|
||||
if (align != 0
|
||||
&& TREE_CODE (type) == RECORD_TYPE
|
||||
&& TYPE_MODE (type) == BLKmode
|
||||
&& TREE_CODE (orig_size) == INTEGER_CST
|
||||
&& compare_tree_int (orig_size, MAX_FIXED_MODE_SIZE) <= 0
|
||||
&& (!size
|
||||
|| (TREE_CODE (size) == INTEGER_CST
|
||||
&& compare_tree_int (size, MAX_FIXED_MODE_SIZE) <= 0))
|
||||
&& value_factor_p (orig_size, align))
|
||||
type = make_packable_type (type, true);
|
||||
/* We used to modify the record in place in some cases, but that could
|
||||
generate incorrect debugging information. So make a new record
|
||||
type and name. */
|
||||
record = make_node (RECORD_TYPE);
|
||||
TYPE_IS_PADDING_P (record) = 1;
|
||||
|
||||
field = create_field_decl (get_identifier ("F"), type, record, 0,
|
||||
NULL_TREE, bitsize_zero_node, 1);
|
||||
if (Present (gnat_entity))
|
||||
TYPE_NAME (record) = create_concat_name (gnat_entity, name_trailer);
|
||||
|
||||
DECL_INTERNAL_P (field) = 1;
|
||||
TYPE_SIZE (record) = size ? size : orig_size;
|
||||
TYPE_SIZE_UNIT (record)
|
||||
= (size ? convert (sizetype,
|
||||
size_binop (CEIL_DIV_EXPR, size, bitsize_unit_node))
|
||||
: TYPE_SIZE_UNIT (type));
|
||||
TYPE_VOLATILE (record)
|
||||
= Present (gnat_entity) && Treat_As_Volatile (gnat_entity);
|
||||
|
||||
TYPE_ALIGN (record) = align;
|
||||
if (orig_align)
|
||||
TYPE_USER_ALIGN (record) = align;
|
||||
|
||||
TYPE_IS_PADDING_P (record) = 1;
|
||||
TYPE_VOLATILE (record)
|
||||
= Present (gnat_entity) && Treat_As_Volatile (gnat_entity);
|
||||
TYPE_SIZE (record) = size ? size : orig_size;
|
||||
TYPE_SIZE_UNIT (record)
|
||||
= convert (sizetype,
|
||||
size_binop (CEIL_DIV_EXPR, TYPE_SIZE (record),
|
||||
bitsize_unit_node));
|
||||
|
||||
/* If we are changing the alignment and the input type is a record with
|
||||
BLKmode and a small constant size, try to make a form that has an
|
||||
integral mode. This might allow the padding record to also have an
|
||||
integral mode, which will be much more efficient. There is no point
|
||||
in doing so if a size is specified unless it is also a small constant
|
||||
size and it is incorrect to do so if we cannot guarantee that the mode
|
||||
will be naturally aligned since the field must always be addressable. */
|
||||
if (align != 0
|
||||
&& TREE_CODE (type) == RECORD_TYPE
|
||||
&& TYPE_MODE (type) == BLKmode
|
||||
&& TREE_CODE (orig_size) == INTEGER_CST
|
||||
&& !TREE_CONSTANT_OVERFLOW (orig_size)
|
||||
&& compare_tree_int (orig_size, MAX_FIXED_MODE_SIZE) <= 0
|
||||
&& (!size
|
||||
|| (TREE_CODE (size) == INTEGER_CST
|
||||
&& compare_tree_int (size, MAX_FIXED_MODE_SIZE) <= 0)))
|
||||
{
|
||||
tree packable_type = make_packable_type (type, true);
|
||||
if (TYPE_MODE (packable_type) != BLKmode
|
||||
&& align >= TYPE_ALIGN (packable_type))
|
||||
type = packable_type;
|
||||
}
|
||||
|
||||
/* Now create the field with the original size. */
|
||||
field = create_field_decl (get_identifier ("F"), type, record, 0,
|
||||
orig_size, bitsize_zero_node, 1);
|
||||
DECL_INTERNAL_P (field) = 1;
|
||||
|
||||
/* Do not finalize it until after the auxiliary record is built. */
|
||||
finish_record_type (record, field, 1, true);
|
||||
|
||||
|
@ -202,7 +202,7 @@ static tree emit_range_check (tree, Node_Id);
|
||||
static tree emit_index_check (tree, tree, tree, tree);
|
||||
static tree emit_check (tree, tree, int);
|
||||
static tree convert_with_check (Entity_Id, tree, bool, bool, bool);
|
||||
static bool larger_record_type_p (tree, tree);
|
||||
static bool smaller_packable_type_p (tree, tree);
|
||||
static bool addressable_p (tree, tree);
|
||||
static tree assoc_to_constructor (Entity_Id, Node_Id, tree);
|
||||
static tree extract_values (tree, tree);
|
||||
@ -2204,11 +2204,11 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
|
||||
of the object if they are distinct, because the expectations
|
||||
of the callee would otherwise not be met:
|
||||
- if it's a justified modular type,
|
||||
- if the actual type is a packable version of it. */
|
||||
- if the actual type is a smaller packable version of it. */
|
||||
else if (TREE_CODE (gnu_name_type) == RECORD_TYPE
|
||||
&& (TYPE_JUSTIFIED_MODULAR_P (gnu_name_type)
|
||||
|| larger_record_type_p (gnu_name_type,
|
||||
TREE_TYPE (gnu_name))))
|
||||
|| smaller_packable_type_p (TREE_TYPE (gnu_name),
|
||||
gnu_name_type)))
|
||||
gnu_name = convert (gnu_name_type, gnu_name);
|
||||
|
||||
/* Make a SAVE_EXPR to both properly account for potential side
|
||||
@ -6120,21 +6120,25 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
|
||||
return convert (gnu_type, gnu_result);
|
||||
}
|
||||
|
||||
/* Return true if RECORD_TYPE, a record type, is larger than TYPE. */
|
||||
/* Return true if TYPE is a smaller packable version of RECORD_TYPE. */
|
||||
|
||||
static bool
|
||||
larger_record_type_p (tree record_type, tree type)
|
||||
smaller_packable_type_p (tree type, tree record_type)
|
||||
{
|
||||
tree rsize, size;
|
||||
tree size, rsize;
|
||||
|
||||
/* Padding types are not considered larger on their own. */
|
||||
if (TYPE_IS_PADDING_P (record_type))
|
||||
/* We're not interested in variants here. */
|
||||
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (record_type))
|
||||
return false;
|
||||
|
||||
rsize = TYPE_SIZE (record_type);
|
||||
size = TYPE_SIZE (type);
|
||||
/* Like a variant, a packable version keeps the original TYPE_NAME. */
|
||||
if (TYPE_NAME (type) != TYPE_NAME (record_type))
|
||||
return false;
|
||||
|
||||
if (!(TREE_CODE (rsize) == INTEGER_CST && TREE_CODE (size) == INTEGER_CST))
|
||||
size = TYPE_SIZE (type);
|
||||
rsize = TYPE_SIZE (record_type);
|
||||
|
||||
if (!(TREE_CODE (size) == INTEGER_CST && TREE_CODE (rsize) == INTEGER_CST))
|
||||
return false;
|
||||
|
||||
return tree_int_cst_lt (size, rsize) != 0;
|
||||
@ -6208,7 +6212,7 @@ addressable_p (tree gnu_expr, tree gnu_type)
|
||||
to be considered in practice. */
|
||||
if (gnu_type
|
||||
&& TREE_CODE (gnu_type) == RECORD_TYPE
|
||||
&& larger_record_type_p (gnu_type, TREE_TYPE (gnu_expr)))
|
||||
&& smaller_packable_type_p (TREE_TYPE (gnu_expr), gnu_type))
|
||||
return false;
|
||||
|
||||
switch (TREE_CODE (gnu_expr))
|
||||
@ -6238,16 +6242,18 @@ addressable_p (tree gnu_expr, tree gnu_type)
|
||||
&& addressable_p (TREE_OPERAND (gnu_expr, 2), NULL_TREE));
|
||||
|
||||
case COMPONENT_REF:
|
||||
return (!DECL_BIT_FIELD (TREE_OPERAND (gnu_expr, 1))
|
||||
&& (!STRICT_ALIGNMENT
|
||||
/* Even with DECL_BIT_FIELD cleared, we have to ensure that
|
||||
the field is sufficiently aligned, in case it is subject
|
||||
to a pragma Component_Alignment. But we don't need to
|
||||
check the alignment of the containing record, as it is
|
||||
guaranteed to be not smaller than that of its most
|
||||
aligned field that is not a bit-field. */
|
||||
|| DECL_ALIGN (TREE_OPERAND (gnu_expr, 1))
|
||||
>= TYPE_ALIGN (TREE_TYPE (gnu_expr)))
|
||||
return (((!DECL_BIT_FIELD (TREE_OPERAND (gnu_expr, 1))
|
||||
/* Even with DECL_BIT_FIELD cleared, we have to ensure that
|
||||
the field is sufficiently aligned, in case it is subject
|
||||
to a pragma Component_Alignment. But we don't need to
|
||||
check the alignment of the containing record, as it is
|
||||
guaranteed to be not smaller than that of its most
|
||||
aligned field that is not a bit-field. */
|
||||
&& (!STRICT_ALIGNMENT
|
||||
|| DECL_ALIGN (TREE_OPERAND (gnu_expr, 1))
|
||||
>= TYPE_ALIGN (TREE_TYPE (gnu_expr))))
|
||||
/* The field of a padding record is always addressable. */
|
||||
|| TYPE_IS_PADDING_P (TREE_TYPE (TREE_OPERAND (gnu_expr, 0))))
|
||||
&& addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE));
|
||||
|
||||
case ARRAY_REF: case ARRAY_RANGE_REF:
|
||||
|
@ -3396,7 +3396,9 @@ convert (tree type, tree expr)
|
||||
&& TYPE_IS_PADDING_P (type) && TYPE_IS_PADDING_P (etype)
|
||||
&& (!TREE_CONSTANT (TYPE_SIZE (type))
|
||||
|| !TREE_CONSTANT (TYPE_SIZE (etype))
|
||||
|| gnat_types_compatible_p (type, etype)))
|
||||
|| gnat_types_compatible_p (type, etype)
|
||||
|| TYPE_NAME (TREE_TYPE (TYPE_FIELDS (type)))
|
||||
== TYPE_NAME (TREE_TYPE (TYPE_FIELDS (etype)))))
|
||||
;
|
||||
|
||||
/* If the output type has padding, convert to the inner type and
|
||||
@ -3405,9 +3407,13 @@ convert (tree type, tree expr)
|
||||
{
|
||||
/* If we previously converted from another type and our type is
|
||||
of variable size, remove the conversion to avoid the need for
|
||||
variable-size temporaries. */
|
||||
variable-size temporaries. Likewise for a conversion between
|
||||
original and packable version. */
|
||||
if (TREE_CODE (expr) == VIEW_CONVERT_EXPR
|
||||
&& !TREE_CONSTANT (TYPE_SIZE (type)))
|
||||
&& (!TREE_CONSTANT (TYPE_SIZE (type))
|
||||
|| (ecode == RECORD_TYPE
|
||||
&& TYPE_NAME (etype)
|
||||
== TYPE_NAME (TREE_TYPE (TREE_OPERAND (expr, 0))))))
|
||||
expr = TREE_OPERAND (expr, 0);
|
||||
|
||||
/* If we are just removing the padding from expr, convert the original
|
||||
@ -3419,7 +3425,10 @@ convert (tree type, tree expr)
|
||||
&& TYPE_IS_PADDING_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
|
||||
&& (!TREE_CONSTANT (TYPE_SIZE (type))
|
||||
|| gnat_types_compatible_p (type,
|
||||
TREE_TYPE (TREE_OPERAND (expr, 0)))))
|
||||
TREE_TYPE (TREE_OPERAND (expr, 0)))
|
||||
|| (ecode == RECORD_TYPE
|
||||
&& TYPE_NAME (etype)
|
||||
== TYPE_NAME (TREE_TYPE (TYPE_FIELDS (type))))))
|
||||
return convert (type, TREE_OPERAND (expr, 0));
|
||||
|
||||
/* If the result type is a padded type with a self-referentially-sized
|
||||
@ -3534,8 +3543,12 @@ convert (tree type, tree expr)
|
||||
|
||||
case CONSTRUCTOR:
|
||||
/* If we are converting a CONSTRUCTOR to a mere variant type, just make
|
||||
a new one in the proper type. */
|
||||
if (gnat_types_compatible_p (type, etype))
|
||||
a new one in the proper type. Likewise for a conversion between
|
||||
original and packable version. */
|
||||
if (code == ecode
|
||||
&& (gnat_types_compatible_p (type, etype)
|
||||
|| (code == RECORD_TYPE
|
||||
&& TYPE_NAME (type) == TYPE_NAME (etype))))
|
||||
{
|
||||
expr = copy_node (expr);
|
||||
TREE_TYPE (expr) = type;
|
||||
@ -3617,7 +3630,8 @@ convert (tree type, tree expr)
|
||||
|
||||
/* If we're converting between two aggregate types that are mere
|
||||
variants, just make a VIEW_CONVERT_EXPR. */
|
||||
else if (AGGREGATE_TYPE_P (type)
|
||||
else if (code == ecode
|
||||
&& AGGREGATE_TYPE_P (type)
|
||||
&& gnat_types_compatible_p (type, etype))
|
||||
return build1 (VIEW_CONVERT_EXPR, type, expr);
|
||||
|
||||
|
@ -693,21 +693,24 @@ build_binary_op (enum tree_code op_code, tree result_type,
|
||||
&& TYPE_ALIGN_OK (right_type))
|
||||
operation_type = right_type;
|
||||
|
||||
/* If we are copying between padded objects of the same underlying
|
||||
type with a non-zero size, use the padded view of the type, this
|
||||
is very likely more efficient; but gnat_to_gnu will have removed
|
||||
the padding on the RHS so we have to make sure that we can safely
|
||||
put it back. */
|
||||
/* If we are copying between padded objects with compatible types, use
|
||||
the padded view of the objects, this is very likely more efficient.
|
||||
Likewise for a padded that is assigned a constructor, in order to
|
||||
avoid putting a VIEW_CONVERT_EXPR on the LHS. But don't do this if
|
||||
we wouldn't have actually copied anything. */
|
||||
else if (TREE_CODE (left_type) == RECORD_TYPE
|
||||
&& TYPE_IS_PADDING_P (left_type)
|
||||
&& TREE_TYPE (TYPE_FIELDS (left_type)) == right_type
|
||||
&& !integer_zerop (TYPE_SIZE (right_type))
|
||||
&& TREE_CONSTANT (TYPE_SIZE (left_type))
|
||||
&& ((TREE_CODE (right_operand) == COMPONENT_REF
|
||||
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (right_operand, 0)))
|
||||
== RECORD_TYPE
|
||||
&& TYPE_IS_PADDING_P
|
||||
(TREE_TYPE (TREE_OPERAND (right_operand, 0))))
|
||||
|| TREE_CODE (right_operand) == CONSTRUCTOR))
|
||||
(TREE_TYPE (TREE_OPERAND (right_operand, 0)))
|
||||
&& gnat_types_compatible_p
|
||||
(left_type,
|
||||
TREE_TYPE (TREE_OPERAND (right_operand, 0))))
|
||||
|| TREE_CODE (right_operand) == CONSTRUCTOR)
|
||||
&& !integer_zerop (TYPE_SIZE (right_type)))
|
||||
operation_type = left_type;
|
||||
|
||||
/* Find the best type to use for copying between aggregate types. */
|
||||
|
@ -1,3 +1,9 @@
|
||||
2008-05-03 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* gnat.dg/alignment4.adb: Adjust.
|
||||
* gnat.dg/alignment5.adb: Likewise.
|
||||
* gnat.dg/alignment6.adb: XFAIL.
|
||||
|
||||
2008-05-03 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
* gcc.dg/tree-ssa/loop-36.c: Cleanup the dump file.
|
||||
|
@ -11,5 +11,5 @@ begin
|
||||
S1 := S2;
|
||||
end;
|
||||
|
||||
-- { dg-final { scan-tree-dump-not "VIEW_CONVERT_EXPR" "gimple" } }
|
||||
-- { dg-final { scan-tree-dump-not ".\F" "gimple" } }
|
||||
-- { dg-final { cleanup-tree-dump "gimple" } }
|
||||
|
@ -27,5 +27,5 @@ begin
|
||||
A_REC := B_REC;
|
||||
end;
|
||||
|
||||
-- { dg-final { scan-tree-dump-not "VIEW_CONVERT_EXPR" "gimple" } }
|
||||
-- { dg-final { scan-tree-dump-not "\.F" "gimple" } }
|
||||
-- { dg-final { cleanup-tree-dump "gimple" } }
|
||||
|
@ -28,5 +28,5 @@ begin
|
||||
B_REC := A_REC;
|
||||
end;
|
||||
|
||||
-- { dg-final { scan-tree-dump-not "VIEW_CONVERT_EXPR" "gimple" } }
|
||||
-- { dg-final { scan-tree-dump-not "VIEW_CONVERT_EXPR" "gimple" { xfail *-*-* } } }
|
||||
-- { dg-final { cleanup-tree-dump "gimple" } }
|
||||
|
Loading…
Reference in New Issue
Block a user