Commit ea6ac859 by Eric Botcazou Committed by Arnaud Charlet

re PR ada/20515 ("stdcall" imports are not handled correctly)

2005-06-10  Eric Botcazou  <ebotcazou@adacore.com>
	    Olivier Hainque  <hainque@adacore.com>
	    Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
	    Pascal Obry  <obry@adacore.com>

	* gigi.h: (build_allocator): Add arg IGNORE_INIT_TYPE.

	* trans.c (call_to_gnu): Issue a warning for users of Starlet when
	making a temporary around a procedure call because of non-addressable
	actual parameter.
	(process_freeze_entity): If entity is a private type, capture size
	information that may have been computed for the full view.
	(tree_transform, case N_Allocator): If have initializing expression,
	check type for Has_Constrained_Partial_View and pass that to
	build_allocator.
	(tree_transform, case N_Return_Statement): Pass extra arg to
	build_allocator.

	* decl.c (annotate_value): Remove early return if -gnatR is not
	specified.
	(gnat_to_gnu_field): Don't make a packable type for a component clause
	if the position is byte aligned, the field is aliased, and the clause
	size isn't a multiple of the packable alignment. It serves no useful
	purpose packing-wise and would be rejected later on.
	(gnat_to_gnu_entity, case object): Pass extra arg to build_allocator.

	PR ada/20515
	(gnat_to_gnu_entity): Remove use of macro _WIN32 which is wrong in the
	context of cross compilers. We use TARGET_DLLIMPORT_DECL_ATTRIBUTES
	instead.
	(create_concat_name): Idem.

From-SVN: r101070
parent 8704d4b3
...@@ -958,8 +958,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -958,8 +958,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
post_error ("Storage_Error will be raised at run-time?", post_error ("Storage_Error will be raised at run-time?",
gnat_entity); gnat_entity);
gnu_expr = build_allocator (gnu_alloc_type, gnu_expr, gnu_expr = build_allocator (gnu_alloc_type, gnu_expr, gnu_type,
gnu_type, 0, 0, gnat_entity); 0, 0, gnat_entity, false);
} }
else else
{ {
...@@ -3630,7 +3630,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -3630,7 +3630,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
if (list_length (gnu_return_list) == 1) if (list_length (gnu_return_list) == 1)
gnu_return_type = TREE_TYPE (TREE_PURPOSE (gnu_return_list)); gnu_return_type = TREE_TYPE (TREE_PURPOSE (gnu_return_list));
#ifdef _WIN32 #ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
if (Convention (gnat_entity) == Convention_Stdcall) if (Convention (gnat_entity) == Convention_Stdcall)
{ {
struct attrib *attr struct attrib *attr
...@@ -5111,7 +5111,6 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed, ...@@ -5111,7 +5111,6 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
{ {
tree gnu_field_id = get_entity_name (gnat_field); tree gnu_field_id = get_entity_name (gnat_field);
tree gnu_field_type = gnat_to_gnu_type (Etype (gnat_field)); tree gnu_field_type = gnat_to_gnu_type (Etype (gnat_field));
tree gnu_orig_field_type = gnu_field_type;
tree gnu_pos = 0; tree gnu_pos = 0;
tree gnu_size = 0; tree gnu_size = 0;
tree gnu_field; tree gnu_field;
...@@ -5138,25 +5137,48 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed, ...@@ -5138,25 +5137,48 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
gnat_field, FIELD_DECL, false, true); gnat_field, FIELD_DECL, false, true);
/* If we are packing this record, have a specified size that's smaller than /* If we are packing this record, have a specified size that's smaller than
that of the field type, or a position is specified, and the field type that of the field type, or a position is specified, and the field type is
is also a record that's BLKmode and with a small constant size, see if also a record that's BLKmode and with a small constant size, see if we
we can get a better form of the type that allows more packing. If we can get a better form of the type that allows more packing. If we can,
can, show a size was specified for it if there wasn't one so we know to show a size was specified for it if there wasn't one so we know to make
make this a bitfield and avoid making things wider. */ this a bitfield and avoid making things wider. */
if (TREE_CODE (gnu_field_type) == RECORD_TYPE if (TREE_CODE (gnu_field_type) == RECORD_TYPE
&& TYPE_MODE (gnu_field_type) == BLKmode && TYPE_MODE (gnu_field_type) == BLKmode
&& host_integerp (TYPE_SIZE (gnu_field_type), 1) && host_integerp (TYPE_SIZE (gnu_field_type), 1)
&& compare_tree_int (TYPE_SIZE (gnu_field_type), BIGGEST_ALIGNMENT) <= 0 && compare_tree_int (TYPE_SIZE (gnu_field_type), BIGGEST_ALIGNMENT) <= 0
&& (packed == 1 && (packed == 1
|| (gnu_size && tree_int_cst_lt (gnu_size, || (gnu_size
TYPE_SIZE (gnu_field_type))) && tree_int_cst_lt (gnu_size, TYPE_SIZE (gnu_field_type)))
|| Present (Component_Clause (gnat_field)))) || Present (Component_Clause (gnat_field))))
{ {
gnu_field_type = make_packable_type (gnu_field_type); /* See what the alternate type and size would be. */
tree gnu_packable_type = make_packable_type (gnu_field_type);
if (gnu_field_type != gnu_orig_field_type && !gnu_size)
/* Compute whether we should avoid the substitution. */
int reject =
/* There is no point subtituting if there is no change. */
(gnu_packable_type == gnu_field_type
||
/* The size of an aliased field must be an exact multiple of the
type's alignment, which the substitution might increase. Reject
substitutions that would so invalidate a component clause when the
specified position is byte aligned, as the change would have no
real benefit from the packing standpoint anyway. */
(Is_Aliased (gnat_field)
&& Present (Component_Clause (gnat_field))
&& UI_To_Int (Component_Bit_Offset (gnat_field)) % BITS_PER_UNIT == 0
&& tree_low_cst (gnu_size, 1) % TYPE_ALIGN (gnu_packable_type) != 0)
);
/* Substitute unless told otherwise. */
if (!reject)
{
gnu_field_type = gnu_packable_type;
if (gnu_size == 0)
gnu_size = rm_size (gnu_field_type); gnu_size = rm_size (gnu_field_type);
} }
}
/* If we are packing the record and the field is BLKmode, round the /* If we are packing the record and the field is BLKmode, round the
size up to a byte boundary. */ size up to a byte boundary. */
...@@ -5678,10 +5700,6 @@ annotate_value (tree gnu_size) ...@@ -5678,10 +5700,6 @@ annotate_value (tree gnu_size)
int i; int i;
int size; int size;
/* If back annotation is suppressed by the front end, return No_Uint */
if (!Back_Annotate_Rep_Info)
return No_Uint;
/* See if we've already saved the value for this node. */ /* See if we've already saved the value for this node. */
if (EXPR_P (gnu_size) && TREE_COMPLEXITY (gnu_size)) if (EXPR_P (gnu_size) && TREE_COMPLEXITY (gnu_size))
return (Node_Ref_Or_Val) TREE_COMPLEXITY (gnu_size); return (Node_Ref_Or_Val) TREE_COMPLEXITY (gnu_size);
...@@ -6606,7 +6624,7 @@ create_concat_name (Entity_Id gnat_entity, const char *suffix) ...@@ -6606,7 +6624,7 @@ create_concat_name (Entity_Id gnat_entity, const char *suffix)
Get_External_Name_With_Suffix (gnat_entity, fp); Get_External_Name_With_Suffix (gnat_entity, fp);
#ifdef _WIN32 #ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
/* A variable using the Stdcall convention (meaning we are running /* A variable using the Stdcall convention (meaning we are running
on a Windows box) live in a DLL. Here we adjust its name to use on a Windows box) live in a DLL. Here we adjust its name to use
the jump-table, the _imp__NAME contains the address for the NAME the jump-table, the _imp__NAME contains the address for the NAME
......
...@@ -709,10 +709,13 @@ extern tree build_call_alloc_dealloc (tree gnu_obj, tree gnu_size, ...@@ -709,10 +709,13 @@ extern tree build_call_alloc_dealloc (tree gnu_obj, tree gnu_size,
RESULT_TYPE, which must be some type of pointer. Return the tree. RESULT_TYPE, which must be some type of pointer. Return the tree.
GNAT_PROC and GNAT_POOL optionally give the procedure to call and GNAT_PROC and GNAT_POOL optionally give the procedure to call and
the storage pool to use. GNAT_NODE is used to provide an error the storage pool to use. GNAT_NODE is used to provide an error
location for restriction violations messages. */ location for restriction violations messages. If IGNORE_INIT_TYPE is
true, ignore the type of INIT for the purpose of determining the size;
this will cause the maximum size to be allocated if TYPE is of
self-referential size. */
extern tree build_allocator (tree type, tree init, tree result_type, extern tree build_allocator (tree type, tree init, tree result_type,
Entity_Id gnat_proc, Entity_Id gnat_pool, Entity_Id gnat_proc, Entity_Id gnat_pool,
Node_Id gnat_node); Node_Id gnat_node, bool);
/* Fill in a VMS descriptor for EXPR and return a constructor for it. /* Fill in a VMS descriptor for EXPR and return a constructor for it.
GNAT_FORMAL is how we find the descriptor record. */ GNAT_FORMAL is how we find the descriptor record. */
......
...@@ -592,6 +592,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute) ...@@ -592,6 +592,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
/* If we are taking 'Address of an unconstrained object, this is the /* If we are taking 'Address of an unconstrained object, this is the
pointer to the underlying array. */ pointer to the underlying array. */
if (attribute == Attr_Address)
gnu_prefix = maybe_unconstrained_array (gnu_prefix); gnu_prefix = maybe_unconstrained_array (gnu_prefix);
/* ... fall through ... */ /* ... fall through ... */
...@@ -1633,6 +1634,27 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target) ...@@ -1633,6 +1634,27 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
tree gnu_copy = gnu_name; tree gnu_copy = gnu_name;
tree gnu_temp; tree gnu_temp;
/* For users of Starlet we issue a warning because the
interface apparently assumes that by-ref parameters
outlive the procedure invocation. The code still
will not work as intended, but we cannot do much
better since other low-level parts of the back-end
would allocate temporaries at will because of the
misalignment if we did not do so here. */
if (Is_Valued_Procedure (Entity (Name (gnat_node))))
{
post_error
("?possible violation of implicit assumption",
gnat_actual);
post_error_ne
("?made by pragma Import_Valued_Procedure on &",
gnat_actual, Entity (Name (gnat_node)));
post_error_ne
("?because of misalignment of &",
gnat_actual, gnat_formal);
}
/* Remove any unpadding on the actual and make a copy. But if /* Remove any unpadding on the actual and make a copy. But if
the actual is a justified modular type, first convert the actual is a justified modular type, first convert
to it. */ to it. */
...@@ -3319,6 +3341,7 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -3319,6 +3341,7 @@ gnat_to_gnu (Node_Id gnat_node)
{ {
tree gnu_init = 0; tree gnu_init = 0;
tree gnu_type; tree gnu_type;
bool ignore_init_type = false;
gnat_temp = Expression (gnat_node); gnat_temp = Expression (gnat_node);
...@@ -3334,6 +3357,7 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -3334,6 +3357,7 @@ gnat_to_gnu (Node_Id gnat_node)
Entity_Id gnat_desig_type Entity_Id gnat_desig_type
= Designated_Type (Underlying_Type (Etype (gnat_node))); = Designated_Type (Underlying_Type (Etype (gnat_node)));
ignore_init_type = Has_Constrained_Partial_View (gnat_desig_type);
gnu_init = gnat_to_gnu (Expression (gnat_temp)); gnu_init = gnat_to_gnu (Expression (gnat_temp));
gnu_init = maybe_unconstrained_array (gnu_init); gnu_init = maybe_unconstrained_array (gnu_init);
...@@ -3361,7 +3385,8 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -3361,7 +3385,8 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_result_type = get_unpadded_type (Etype (gnat_node)); gnu_result_type = get_unpadded_type (Etype (gnat_node));
return build_allocator (gnu_type, gnu_init, gnu_result_type, return build_allocator (gnu_type, gnu_init, gnu_result_type,
Procedure_To_Call (gnat_node), Procedure_To_Call (gnat_node),
Storage_Pool (gnat_node), gnat_node); Storage_Pool (gnat_node), gnat_node,
ignore_init_type);
} }
break; break;
...@@ -3576,7 +3601,7 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -3576,7 +3601,7 @@ gnat_to_gnu (Node_Id gnat_node)
= build_allocator (TREE_TYPE (gnu_ret_val), = build_allocator (TREE_TYPE (gnu_ret_val),
gnu_ret_val, gnu_ret_val,
TREE_TYPE (gnu_subprog_type), TREE_TYPE (gnu_subprog_type),
0, -1, gnat_node); 0, -1, gnat_node, false);
else else
gnu_ret_val gnu_ret_val
= build_allocator (TREE_TYPE (gnu_ret_val), = build_allocator (TREE_TYPE (gnu_ret_val),
...@@ -3584,7 +3609,7 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -3584,7 +3609,7 @@ gnat_to_gnu (Node_Id gnat_node)
TREE_TYPE (gnu_subprog_type), TREE_TYPE (gnu_subprog_type),
Procedure_To_Call (gnat_node), Procedure_To_Call (gnat_node),
Storage_Pool (gnat_node), Storage_Pool (gnat_node),
gnat_node); gnat_node, false);
} }
} }
} }
...@@ -4754,11 +4779,15 @@ process_freeze_entity (Node_Id gnat_node) ...@@ -4754,11 +4779,15 @@ process_freeze_entity (Node_Id gnat_node)
/* Don't do anything for subprograms that may have been elaborated before /* Don't do anything for subprograms that may have been elaborated before
their freeze nodes. This can happen, for example because of an inner call their freeze nodes. This can happen, for example because of an inner call
in an instance body. */ in an instance body, or a previous compilation of a spec for inlining
if (gnu_old purposes. */
if ((gnu_old
&& TREE_CODE (gnu_old) == FUNCTION_DECL && TREE_CODE (gnu_old) == FUNCTION_DECL
&& (Ekind (gnat_entity) == E_Function && (Ekind (gnat_entity) == E_Function
|| Ekind (gnat_entity) == E_Procedure)) || Ekind (gnat_entity) == E_Procedure))
|| (gnu_old
&& (TREE_CODE (TREE_TYPE (gnu_old)) == FUNCTION_TYPE
&& Ekind (gnat_entity) == E_Subprogram_Type)))
return; return;
/* If we have a non-dummy type old tree, we have nothing to do. Unless /* If we have a non-dummy type old tree, we have nothing to do. Unless
...@@ -4798,6 +4827,16 @@ process_freeze_entity (Node_Id gnat_node) ...@@ -4798,6 +4827,16 @@ process_freeze_entity (Node_Id gnat_node)
{ {
gnu_new = gnat_to_gnu_entity (Full_View (gnat_entity), NULL_TREE, 1); gnu_new = gnat_to_gnu_entity (Full_View (gnat_entity), NULL_TREE, 1);
/* Propagate back-annotations from full view to partial view. */
if (Unknown_Alignment (gnat_entity))
Set_Alignment (gnat_entity, Alignment (Full_View (gnat_entity)));
if (Unknown_Esize (gnat_entity))
Set_Esize (gnat_entity, Esize (Full_View (gnat_entity)));
if (Unknown_RM_Size (gnat_entity))
Set_RM_Size (gnat_entity, RM_Size (Full_View (gnat_entity)));
/* The above call may have defined this entity (the simplest example /* The above call may have defined this entity (the simplest example
of this is when we have a private enumeral type since the bounds of this is when we have a private enumeral type since the bounds
will have the public view. */ will have the public view. */
......
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