decl.c (gnat_to_gnu_entity, [...]): Don't early expand pointer initialization values.

2005-12-05  Olivier Hainque  <hainque@adacore.com>

	* decl.c (gnat_to_gnu_entity, renaming object case): Don't early expand
	pointer initialization values. Make a SAVE_EXPR instead. Add comments
	about the use and expansion of SAVE_EXPRs in the various possible
	renaming handling cases.
	(components_to_record, compare_field_bitpos): Sort by DECL_UID, not by
	abusing DECL_FCONTEXT.

From-SVN: r108286
This commit is contained in:
Olivier Hainque 2005-12-09 18:16:11 +01:00 committed by Arnaud Charlet
parent bb4daba346
commit 9582a3cd55

View File

@ -765,14 +765,16 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
the renamed entity or if we need to make a pointer. */
else
{
bool stabilized;
bool stabilized = false;
tree maybe_stable_expr = NULL_TREE;
/* Case 2: If the renaming entity need not be materialized and
the renamed expression is something we can stabilize, use
that for the renaming after forcing the evaluation of any
SAVE_EXPR. At the global level, we can only do this if we
know no SAVE_EXPRs will be made. */
that for the renaming. At the global level, we can only do
this if we know no SAVE_EXPRs need be made, because the
expression we return might be used in arbitrary conditional
branches so we must force the SAVE_EXPRs evaluation
immediately and this requires a function context. */
if (!Materialize_Entity (gnat_entity)
&& (!global_bindings_p ()
|| (staticp (gnu_expr)
@ -812,21 +814,35 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
object, we just make a "bare" pointer, and the renamed
entity is always accessed indirectly through it. */
{
bool has_side_effects = TREE_SIDE_EFFECTS (gnu_expr);
bool expr_has_side_effects = TREE_SIDE_EFFECTS (gnu_expr);
inner_const_flag = TREE_READONLY (gnu_expr);
const_flag = true;
gnu_type = build_reference_type (gnu_type);
/* If a previous attempt at unrestricted
stabilization failed, there is no point trying
again and we can reuse the result without
attaching it to the pointer. */
/* If a previous attempt at unrestricted stabilization
failed, there is no point trying again and we can reuse
the result without attaching it to the pointer. */
if (maybe_stable_expr)
;
/* Otherwise, try to stabilize now, restricting to
lvalues only, and attach the expression to the pointer
if the stabilization succeeds. */
if the stabilization succeeds.
Note that this might introduce SAVE_EXPRs and we don't
check whether we're at the global level or not. This is
fine since we are building a pointer initializer and
neither the pointer nor the initializing expression can
be accessed before the pointer elaboration has taken
place in a correct program.
SAVE_EXPRs will be evaluated at the right spots by either
create_var_decl->expand_decl_init for the non-global case
or build_unit_elab for the global case, and will be
attached to the elaboration procedure by the RTL expander
in the latter case. We have no need to force an early
evaluation here. */
else
{
maybe_stable_expr
@ -842,15 +858,13 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnu_expr
= build_unary_op (ADDR_EXPR, gnu_type, maybe_stable_expr);
if (!global_bindings_p ())
{
/* If the original expression had side effects, put a
SAVE_EXPR around this whole thing. */
if (has_side_effects)
gnu_expr = save_expr (gnu_expr);
add_stmt (gnu_expr);
}
/* If the initial expression has side effects, we might
still have an unstabilized version at this point (for
instance if it involves a function call). Wrap the
result into a SAVE_EXPR now, in case it happens to be
referenced several times. */
if (expr_has_side_effects && ! stabilized)
gnu_expr = save_expr (gnu_expr);
gnu_size = NULL_TREE;
used_by_ref = true;
@ -1001,16 +1015,16 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnu_alloc_type
= TREE_TYPE (TREE_CHAIN (TYPE_FIELDS (gnu_alloc_type)));
if (TREE_CODE (gnu_expr) == CONSTRUCTOR
&& VEC_length (constructor_elt,
CONSTRUCTOR_ELTS (gnu_expr)) == 1)
gnu_expr = 0;
else
gnu_expr
= build_component_ref
(gnu_expr, NULL_TREE,
TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (gnu_expr))),
false);
if (TREE_CODE (gnu_expr) == CONSTRUCTOR
&& 1 == VEC_length (constructor_elt,
CONSTRUCTOR_ELTS (gnu_expr)))
gnu_expr = 0;
else
gnu_expr
= build_component_ref
(gnu_expr, NULL_TREE,
TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (gnu_expr))),
false);
}
if (TREE_CODE (TYPE_SIZE_UNIT (gnu_alloc_type)) == INTEGER_CST
@ -5676,27 +5690,22 @@ components_to_record (tree gnu_record_type, Node_Id component_list,
/* If we have any items in our rep'ed field list, it is not the case that all
the fields in the record have rep clauses, and P_REP_LIST is nonzero,
set it and ignore the items. Otherwise, sort the fields by bit position
and put them into their own record if we have any fields without
rep clauses. */
set it and ignore the items. */
if (gnu_our_rep_list && p_gnu_rep_list && !all_rep)
*p_gnu_rep_list = chainon (*p_gnu_rep_list, gnu_our_rep_list);
else if (gnu_our_rep_list)
{
/* Otherwise, sort the fields by bit position and put them into their
own record if we have any fields without rep clauses. */
tree gnu_rep_type
= (gnu_field_list ? make_node (RECORD_TYPE) : gnu_record_type);
int len = list_length (gnu_our_rep_list);
tree *gnu_arr = (tree *) alloca (sizeof (tree) * len);
int i;
/* Set/abuse DECL_FCONTEXT to increasing integers so we have a
stable sort. */
for (i = 0, gnu_field = gnu_our_rep_list; gnu_field;
gnu_field = TREE_CHAIN (gnu_field), i++)
{
gnu_arr[i] = gnu_field;
DECL_FCONTEXT (gnu_field) = size_int (i);
}
gnu_arr[i] = gnu_field;
qsort (gnu_arr, len, sizeof (tree), compare_field_bitpos);
@ -5708,7 +5717,6 @@ components_to_record (tree gnu_record_type, Node_Id component_list,
TREE_CHAIN (gnu_arr[i]) = gnu_our_rep_list;
gnu_our_rep_list = gnu_arr[i];
DECL_CONTEXT (gnu_arr[i]) = gnu_rep_type;
DECL_FCONTEXT (gnu_arr[i]) = NULL_TREE;
}
if (gnu_field_list)
@ -5734,7 +5742,8 @@ components_to_record (tree gnu_record_type, Node_Id component_list,
}
/* Called via qsort from the above. Returns -1, 1, depending on the
bit positions and ordinals of the two fields. */
bit positions and ordinals of the two fields. Use DECL_UID to ensure
a stable sort. */
static int
compare_field_bitpos (const PTR rt1, const PTR rt2)
@ -5743,9 +5752,7 @@ compare_field_bitpos (const PTR rt1, const PTR rt2)
tree *t2 = (tree *) rt2;
if (tree_int_cst_equal (bit_position (*t1), bit_position (*t2)))
return
(tree_int_cst_lt (DECL_FCONTEXT (*t1), DECL_FCONTEXT (*t2))
? -1 : 1);
return DECL_UID (*t1) < DECL_UID (*t2) ? -1 : 1;
else if (tree_int_cst_lt (bit_position (*t1), bit_position (*t2)))
return -1;
else