Commit 842d4ee2 by Eric Botcazou Committed by Eric Botcazou

gigi.h (make_packable_type): Declare.

	* gcc-interface/gigi.h (make_packable_type): Declare.
	(make_type_from_size): Likewise.
	(relate_alias_sets): Likewise.
	(maybe_pad_type): Adjust.
	(init_gnat_to_gnu): Delete.
	(destroy_gnat_to_gnu): Likewise.
	(init_dummy_type): Likewise.
	(destroy_dummy_type): Likewise.
	(init_gnat_utils): Declare.
	(destroy_gnat_utils): Likewise.
	(ceil_pow2): New inline function.
	* gcc-interface/decl.c (gnat_to_gnu_entity): Use ceil_pow2.
	<object>: Pass True for the final processing of alignment and size.
	<E_Subprogram_Type>: Only create the TYPE_DECL for a padded return
	type if necessary.
	(round_up_to_align): Delete.
	(ceil_alignment): Likewise.
	(relate_alias_sets): Move to...
	(make_aligning_type): Likewise.
	(make_packable_type): Likewise.
	(maybe_pad_type): Likewise.
	(make_type_from_size): Likewise.
	* gcc-interface/utils.c (MAX_BITS_PER_WORD): Delete.
	(struct pad_type_hash): New type.
	(pad_type_hash_table): New static variable.
	(init_gnat_to_gnu): Merge into...
	(init_dummy_type): Likewise.
	(init_gnat_utils): ...this.  New function.
	(destroy_gnat_to_gnu): Merge into...
	(destroy_dummy_type): Likewise.
	(destroy_gnat_utils): ...this.  New function.
	(pad_type_hash_marked_p): New function.
	(pad_type_hash_hash): Likewise.
	(pad_type_hash_eq): Likewise.
	(relate_alias_sets): ...here.
	(make_aligning_type): Likewise.
	(make_packable_type): Likewise.
	(maybe_pad_type): Likewise.  Change same_rm_size parameter into
	set_rm_size; do not set TYPE_ADA_SIZE if it is false.  Do not set
	null as Ada size.  Do not set TYPE_VOLATILE on the padded type.  If it
	is complete and has constant size, canonicalize it.  Bail out earlier
	if a warning need not be issued.
	(make_type_from_size): Likewise.
	<INTEGER_TYPE>: Bail out if size is too large
	(gnat_types_compatible_p): Do not deal with padded types.
	(convert): Compare main variants for padded types.
	* gcc-interface/trans.c (gigi): Call {init|destroy}_gnat_utils.
	(gnat_to_gnu): Do not convert at the end for a call to a function that
	returns an unconstrained type with default discriminant.
	(Attribute_to_gnu) <Attr_Size>: Simplify handling of padded objects.
	* gcc-interface/utils2.c (build_binary_op) <MODIFY_EXPR>: Likewise.
	Do not use the padded type if it is BLKmode and the inner type is
	non-BLKmode.

From-SVN: r187206
parent 62957409
2012-05-06 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/gigi.h (make_packable_type): Declare.
(make_type_from_size): Likewise.
(relate_alias_sets): Likewise.
(maybe_pad_type): Adjust.
(init_gnat_to_gnu): Delete.
(destroy_gnat_to_gnu): Likewise.
(init_dummy_type): Likewise.
(destroy_dummy_type): Likewise.
(init_gnat_utils): Declare.
(destroy_gnat_utils): Likewise.
(ceil_pow2): New inline function.
* gcc-interface/decl.c (gnat_to_gnu_entity): Use ceil_pow2.
<object>: Pass True for the final processing of alignment and size.
<E_Subprogram_Type>: Only create the TYPE_DECL for a padded return
type if necessary.
(round_up_to_align): Delete.
(ceil_alignment): Likewise.
(relate_alias_sets): Move to...
(make_aligning_type): Likewise.
(make_packable_type): Likewise.
(maybe_pad_type): Likewise.
(make_type_from_size): Likewise.
* gcc-interface/utils.c (MAX_BITS_PER_WORD): Delete.
(struct pad_type_hash): New type.
(pad_type_hash_table): New static variable.
(init_gnat_to_gnu): Merge into...
(init_dummy_type): Likewise.
(init_gnat_utils): ...this. New function.
(destroy_gnat_to_gnu): Merge into...
(destroy_dummy_type): Likewise.
(destroy_gnat_utils): ...this. New function.
(pad_type_hash_marked_p): New function.
(pad_type_hash_hash): Likewise.
(pad_type_hash_eq): Likewise.
(relate_alias_sets): ...here.
(make_aligning_type): Likewise.
(make_packable_type): Likewise.
(maybe_pad_type): Likewise. Change same_rm_size parameter into
set_rm_size; do not set TYPE_ADA_SIZE if it is false. Do not set
null as Ada size. Do not set TYPE_VOLATILE on the padded type. If it
is complete and has constant size, canonicalize it. Bail out earlier
if a warning need not be issued.
(make_type_from_size): Likewise.
<INTEGER_TYPE>: Bail out if size is too large
(gnat_types_compatible_p): Do not deal with padded types.
(convert): Compare main variants for padded types.
* gcc-interface/trans.c (gigi): Call {init|destroy}_gnat_utils.
(gnat_to_gnu): Do not convert at the end for a call to a function that
returns an unconstrained type with default discriminant.
(Attribute_to_gnu) <Attr_Size>: Simplify handling of padded objects.
* gcc-interface/utils2.c (build_binary_op) <MODIFY_EXPR>: Likewise.
Do not use the padded type if it is BLKmode and the inner type is
non-BLKmode.
2012-05-02 Pascal Obry <obry@adacore.com> 2012-05-02 Pascal Obry <obry@adacore.com>
Revert Revert
......
...@@ -123,18 +123,48 @@ extern tree get_minimal_subprog_decl (Entity_Id gnat_entity); ...@@ -123,18 +123,48 @@ extern tree get_minimal_subprog_decl (Entity_Id gnat_entity);
extern tree make_aligning_type (tree type, unsigned int align, tree size, extern tree make_aligning_type (tree type, unsigned int align, tree size,
unsigned int base_align, int room); unsigned int base_align, int room);
/* TYPE is a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE that is being used
as the field type of a packed record if IN_RECORD is true, or as the
component type of a packed array if IN_RECORD is false. See if we can
rewrite it either as a type that has a non-BLKmode, which we can pack
tighter in the packed record case, or as a smaller type. If so, return
the new type. If not, return the original type. */
extern tree make_packable_type (tree type, bool in_record);
/* Given a type TYPE, return a new type whose size is appropriate for SIZE.
If TYPE is the best type, return it. Otherwise, make a new type. We
only support new integral and pointer types. FOR_BIASED is true if
we are making a biased type. */
extern tree make_type_from_size (tree type, tree size_tree, bool for_biased);
/* Ensure that TYPE has SIZE and ALIGN. Make and return a new padded type /* Ensure that TYPE has SIZE and ALIGN. Make and return a new padded type
if needed. We have already verified that SIZE and TYPE are large enough. if needed. We have already verified that SIZE and TYPE are large enough.
GNAT_ENTITY is used to name the resulting record and to issue a warning. GNAT_ENTITY is used to name the resulting record and to issue a warning.
IS_COMPONENT_TYPE is true if this is being done for the component type IS_COMPONENT_TYPE is true if this is being done for the component type of
of an array. IS_USER_TYPE is true if we must complete the original type. an array. IS_USER_TYPE is true if the original type needs to be completed.
DEFINITION is true if this type is being defined. SAME_RM_SIZE is true DEFINITION is true if this type is being defined. SET_RM_SIZE is true if
if the RM size of the resulting type is to be set to SIZE too; otherwise, the RM size of the resulting type is to be set to SIZE too. */
it's set to the RM size of the original type. */
extern tree maybe_pad_type (tree type, tree size, unsigned int align, extern tree maybe_pad_type (tree type, tree size, unsigned int align,
Entity_Id gnat_entity, bool is_component_type, Entity_Id gnat_entity, bool is_component_type,
bool is_user_type, bool definition, bool is_user_type, bool definition,
bool same_rm_size); bool set_rm_size);
enum alias_set_op
{
ALIAS_SET_COPY,
ALIAS_SET_SUBSET,
ALIAS_SET_SUPERSET
};
/* Relate the alias sets of GNU_NEW_TYPE and GNU_OLD_TYPE according to OP.
If this is a multi-dimensional array type, do this recursively.
OP may be
- ALIAS_SET_COPY: the new set is made a copy of the old one.
- ALIAS_SET_SUPERSET: the new set is made a superset of the old one.
- ALIAS_SET_SUBSET: the new set is made a subset of the old one. */
extern void relate_alias_sets (tree gnu_new_type, tree gnu_old_type,
enum alias_set_op op);
/* Given a GNU tree and a GNAT list of choices, generate an expression to test /* Given a GNU tree and a GNAT list of choices, generate an expression to test
the value passed against the list of choices. */ the value passed against the list of choices. */
...@@ -497,11 +527,11 @@ extern tree convert_to_index_type (tree expr); ...@@ -497,11 +527,11 @@ extern tree convert_to_index_type (tree expr);
/* Routines created solely for the tree translator's sake. Their prototypes /* Routines created solely for the tree translator's sake. Their prototypes
can be changed as desired. */ can be changed as desired. */
/* Initialize the association of GNAT nodes to GCC trees. */ /* Initialize data structures of the utils.c module. */
extern void init_gnat_to_gnu (void); extern void init_gnat_utils (void);
/* Destroy the association of GNAT nodes to GCC trees. */ /* Destroy data structures of the utils.c module. */
extern void destroy_gnat_to_gnu (void); extern void destroy_gnat_utils (void);
/* GNAT_ENTITY is a GNAT tree node for a defining identifier. /* GNAT_ENTITY is a GNAT tree node for a defining identifier.
GNU_DECL is the GCC tree which is to be associated with GNU_DECL is the GCC tree which is to be associated with
...@@ -519,12 +549,6 @@ extern tree get_gnu_tree (Entity_Id gnat_entity); ...@@ -519,12 +549,6 @@ extern tree get_gnu_tree (Entity_Id gnat_entity);
/* Return nonzero if a GCC tree has been associated with GNAT_ENTITY. */ /* Return nonzero if a GCC tree has been associated with GNAT_ENTITY. */
extern bool present_gnu_tree (Entity_Id gnat_entity); extern bool present_gnu_tree (Entity_Id gnat_entity);
/* Initialize the association of GNAT nodes to GCC trees as dummies. */
extern void init_dummy_type (void);
/* Destroy the association of GNAT nodes to GCC trees as dummies. */
extern void destroy_dummy_type (void);
/* Make a dummy type corresponding to GNAT_TYPE. */ /* Make a dummy type corresponding to GNAT_TYPE. */
extern tree make_dummy_type (Entity_Id gnat_type); extern tree make_dummy_type (Entity_Id gnat_type);
...@@ -1008,3 +1032,9 @@ extern void enumerate_modes (void (*f) (const char *, int, int, int, int, int, ...@@ -1008,3 +1032,9 @@ extern void enumerate_modes (void (*f) (const char *, int, int, int, int, int,
/* Convenient shortcuts. */ /* Convenient shortcuts. */
#define VECTOR_TYPE_P(TYPE) (TREE_CODE (TYPE) == VECTOR_TYPE) #define VECTOR_TYPE_P(TYPE) (TREE_CODE (TYPE) == VECTOR_TYPE)
static inline unsigned HOST_WIDE_INT
ceil_pow2 (unsigned HOST_WIDE_INT x)
{
return (unsigned HOST_WIDE_INT) 1 << (floor_log2 (x - 1) + 1);
}
...@@ -338,8 +338,7 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED, ...@@ -338,8 +338,7 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
/* Initialize ourselves. */ /* Initialize ourselves. */
init_code_table (); init_code_table ();
init_gnat_to_gnu (); init_gnat_utils ();
init_dummy_type ();
/* If we are just annotating types, give VOID_TYPE zero sizes to avoid /* If we are just annotating types, give VOID_TYPE zero sizes to avoid
errors. */ errors. */
...@@ -685,8 +684,7 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED, ...@@ -685,8 +684,7 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
} }
/* Destroy ourselves. */ /* Destroy ourselves. */
destroy_gnat_to_gnu (); destroy_gnat_utils ();
destroy_dummy_type ();
/* We cannot track the location of errors past this point. */ /* We cannot track the location of errors past this point. */
error_gnat_node = Empty; error_gnat_node = Empty;
...@@ -1501,34 +1499,25 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute) ...@@ -1501,34 +1499,25 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
gnu_type = TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (gnu_type))); gnu_type = TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (gnu_type)));
} }
/* If we're looking for the size of a field, return the field size. /* If we're looking for the size of a field, return the field size. */
Otherwise, if the prefix is an object, or if we're looking for
'Object_Size or 'Max_Size_In_Storage_Elements, the result is the
GCC size of the type. Otherwise, it is the RM size of the type. */
if (TREE_CODE (gnu_prefix) == COMPONENT_REF) if (TREE_CODE (gnu_prefix) == COMPONENT_REF)
gnu_result = DECL_SIZE (TREE_OPERAND (gnu_prefix, 1)); gnu_result = DECL_SIZE (TREE_OPERAND (gnu_prefix, 1));
else if (TREE_CODE (gnu_prefix) != TYPE_DECL
/* Otherwise, if the prefix is an object, or if we are looking for
'Object_Size or 'Max_Size_In_Storage_Elements, the result is the
GCC size of the type. We make an exception for padded objects,
as we do not take into account alignment promotions for the size.
This is in keeping with the object case of gnat_to_gnu_entity. */
else if ((TREE_CODE (gnu_prefix) != TYPE_DECL
&& !(TYPE_IS_PADDING_P (gnu_type)
&& TREE_CODE (gnu_expr) == COMPONENT_REF))
|| attribute == Attr_Object_Size || attribute == Attr_Object_Size
|| attribute == Attr_Max_Size_In_Storage_Elements) || attribute == Attr_Max_Size_In_Storage_Elements)
{ {
/* If the prefix is an object of a padded type, the GCC size isn't /* If this is a dereference and we have a special dynamic constrained
relevant to the programmer. Normally what we want is the RM size, subtype on the prefix, use it to compute the size; otherwise, use
which was set from the specified size, but if it was not set, we the designated subtype. */
want the size of the field. Using the MAX of those two produces if (Nkind (Prefix (gnat_node)) == N_Explicit_Dereference)
the right result in all cases. Don't use the size of the field
if it's self-referential, since that's never what's wanted. */
if (TREE_CODE (gnu_prefix) != TYPE_DECL
&& TYPE_IS_PADDING_P (gnu_type)
&& TREE_CODE (gnu_expr) == COMPONENT_REF)
{
gnu_result = rm_size (gnu_type);
if (!CONTAINS_PLACEHOLDER_P
(DECL_SIZE (TREE_OPERAND (gnu_expr, 1))))
gnu_result
= size_binop (MAX_EXPR, gnu_result,
DECL_SIZE (TREE_OPERAND (gnu_expr, 1)));
}
else if (Nkind (Prefix (gnat_node)) == N_Explicit_Dereference)
{ {
Node_Id gnat_deref = Prefix (gnat_node); Node_Id gnat_deref = Prefix (gnat_node);
Node_Id gnat_actual_subtype Node_Id gnat_actual_subtype
...@@ -1547,12 +1536,12 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute) ...@@ -1547,12 +1536,12 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
get_identifier ("SIZE"), get_identifier ("SIZE"),
false); false);
} }
gnu_result = TYPE_SIZE (gnu_type);
} }
else
gnu_result = TYPE_SIZE (gnu_type); gnu_result = TYPE_SIZE (gnu_type);
} }
/* Otherwise, the result is the RM size of the type. */
else else
gnu_result = rm_size (gnu_type); gnu_result = rm_size (gnu_type);
...@@ -6921,15 +6910,10 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -6921,15 +6910,10 @@ gnat_to_gnu (Node_Id gnat_node)
else if (TREE_CODE (gnu_result) == CALL_EXPR else if (TREE_CODE (gnu_result) == CALL_EXPR
&& TYPE_IS_PADDING_P (TREE_TYPE (gnu_result)) && TYPE_IS_PADDING_P (TREE_TYPE (gnu_result))
&& TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_result)))
== gnu_result_type
&& CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_result_type))) && CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_result_type)))
{ ;
/* ??? We need to convert if the padded type has fixed size because
gnat_types_compatible_p will say that padded types are compatible
but the gimplifier will not and, therefore, will ultimately choke
if there isn't a conversion added early. */
if (TREE_CODE (TYPE_SIZE (TREE_TYPE (gnu_result))) == INTEGER_CST)
gnu_result = convert (gnu_result_type, gnu_result);
}
else if (TREE_TYPE (gnu_result) != gnu_result_type) else if (TREE_TYPE (gnu_result) != gnu_result_type)
gnu_result = convert (gnu_result_type, gnu_result); gnu_result = convert (gnu_result_type, gnu_result);
......
...@@ -789,16 +789,28 @@ build_binary_op (enum tree_code op_code, tree result_type, ...@@ -789,16 +789,28 @@ build_binary_op (enum tree_code op_code, tree result_type,
else if (TYPE_IS_PADDING_P (left_type) else if (TYPE_IS_PADDING_P (left_type)
&& TREE_CONSTANT (TYPE_SIZE (left_type)) && TREE_CONSTANT (TYPE_SIZE (left_type))
&& ((TREE_CODE (right_operand) == COMPONENT_REF && ((TREE_CODE (right_operand) == COMPONENT_REF
&& TYPE_IS_PADDING_P && TYPE_MAIN_VARIANT (left_type)
(TREE_TYPE (TREE_OPERAND (right_operand, 0))) == TYPE_MAIN_VARIANT
&& gnat_types_compatible_p (TREE_TYPE (TREE_OPERAND (right_operand, 0))))
(left_type,
TREE_TYPE (TREE_OPERAND (right_operand, 0))))
|| (TREE_CODE (right_operand) == CONSTRUCTOR || (TREE_CODE (right_operand) == CONSTRUCTOR
&& !CONTAINS_PLACEHOLDER_P && !CONTAINS_PLACEHOLDER_P
(DECL_SIZE (TYPE_FIELDS (left_type))))) (DECL_SIZE (TYPE_FIELDS (left_type)))))
&& !integer_zerop (TYPE_SIZE (right_type))) && !integer_zerop (TYPE_SIZE (right_type)))
operation_type = left_type; {
/* We make an exception for a BLKmode type padding a non-BLKmode
inner type and do the conversion of the LHS right away, since
unchecked_convert wouldn't do it properly. */
if (TYPE_MODE (left_type) == BLKmode
&& TYPE_MODE (right_type) != BLKmode
&& TREE_CODE (right_operand) != CONSTRUCTOR)
{
operation_type = right_type;
left_operand = convert (operation_type, left_operand);
left_type = operation_type;
}
else
operation_type = left_type;
}
/* If we have a call to a function that returns an unconstrained type /* If we have a call to a function that returns an unconstrained type
with default discriminant on the RHS, use the RHS type (which is with default discriminant on the RHS, use the RHS type (which is
......
2012-05-04 Eric Botcazou <ebotcazou@adacore.com>
* gcc.target/ia64/pr48496.c: New test.
* gcc.target/ia64/pr52657.c: Likewise.
2012-05-05 Manuel López-Ibáñez <manu@gcc.gnu.org> 2012-05-05 Manuel López-Ibáñez <manu@gcc.gnu.org>
PR c/43772 PR c/43772
......
-- { dg-do compile }
with Discr36_Pkg;
package body Discr36 is
function N return Natural is begin return 0; end;
type Arr is array (1 .. N) of R;
function My_Func is new Discr36_Pkg.Func (Arr);
procedure Proc is
A : constant Arr := My_Func;
begin
null;
end;
end Discr36;
package Discr36 is
type R (D : Boolean := True) is record
case D is
when True => I : Integer;
when False => null;
end case;
end record;
function N return Natural;
end Discr36;
package body Discr36_Pkg is
function Func return T is
Ret : T;
pragma Warnings (Off, Ret);
begin
return Ret;
end;
end Discr36_Pkg;
package Discr36_Pkg is
generic
type T is private;
function Func return T;
end Discr36_Pkg;
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