Commit 9582a3cd by Olivier Hainque Committed by Arnaud Charlet

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
parent bb4daba3
...@@ -765,14 +765,16 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -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. */ the renamed entity or if we need to make a pointer. */
else else
{ {
bool stabilized; bool stabilized = false;
tree maybe_stable_expr = NULL_TREE; tree maybe_stable_expr = NULL_TREE;
/* Case 2: If the renaming entity need not be materialized and /* Case 2: If the renaming entity need not be materialized and
the renamed expression is something we can stabilize, use the renamed expression is something we can stabilize, use
that for the renaming after forcing the evaluation of any that for the renaming. At the global level, we can only do
SAVE_EXPR. At the global level, we can only do this if we this if we know no SAVE_EXPRs need be made, because the
know no SAVE_EXPRs will be made. */ 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) if (!Materialize_Entity (gnat_entity)
&& (!global_bindings_p () && (!global_bindings_p ()
|| (staticp (gnu_expr) || (staticp (gnu_expr)
...@@ -812,21 +814,35 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -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 object, we just make a "bare" pointer, and the renamed
entity is always accessed indirectly through it. */ 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); inner_const_flag = TREE_READONLY (gnu_expr);
const_flag = true; const_flag = true;
gnu_type = build_reference_type (gnu_type); gnu_type = build_reference_type (gnu_type);
/* If a previous attempt at unrestricted /* If a previous attempt at unrestricted stabilization
stabilization failed, there is no point trying failed, there is no point trying again and we can reuse
again and we can reuse the result without the result without attaching it to the pointer. */
attaching it to the pointer. */
if (maybe_stable_expr) if (maybe_stable_expr)
; ;
/* Otherwise, try to stabilize now, restricting to /* Otherwise, try to stabilize now, restricting to
lvalues only, and attach the expression to the pointer 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 else
{ {
maybe_stable_expr maybe_stable_expr
...@@ -842,15 +858,13 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -842,15 +858,13 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnu_expr gnu_expr
= build_unary_op (ADDR_EXPR, gnu_type, maybe_stable_expr); = build_unary_op (ADDR_EXPR, gnu_type, maybe_stable_expr);
if (!global_bindings_p ()) /* If the initial expression has side effects, we might
{ still have an unstabilized version at this point (for
/* If the original expression had side effects, put a instance if it involves a function call). Wrap the
SAVE_EXPR around this whole thing. */ result into a SAVE_EXPR now, in case it happens to be
if (has_side_effects) referenced several times. */
gnu_expr = save_expr (gnu_expr); if (expr_has_side_effects && ! stabilized)
gnu_expr = save_expr (gnu_expr);
add_stmt (gnu_expr);
}
gnu_size = NULL_TREE; gnu_size = NULL_TREE;
used_by_ref = true; used_by_ref = true;
...@@ -1001,16 +1015,16 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -1001,16 +1015,16 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnu_alloc_type gnu_alloc_type
= TREE_TYPE (TREE_CHAIN (TYPE_FIELDS (gnu_alloc_type))); = TREE_TYPE (TREE_CHAIN (TYPE_FIELDS (gnu_alloc_type)));
if (TREE_CODE (gnu_expr) == CONSTRUCTOR if (TREE_CODE (gnu_expr) == CONSTRUCTOR
&& VEC_length (constructor_elt, && 1 == VEC_length (constructor_elt,
CONSTRUCTOR_ELTS (gnu_expr)) == 1) CONSTRUCTOR_ELTS (gnu_expr)))
gnu_expr = 0; gnu_expr = 0;
else else
gnu_expr gnu_expr
= build_component_ref = build_component_ref
(gnu_expr, NULL_TREE, (gnu_expr, NULL_TREE,
TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (gnu_expr))), TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (gnu_expr))),
false); false);
} }
if (TREE_CODE (TYPE_SIZE_UNIT (gnu_alloc_type)) == INTEGER_CST 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, ...@@ -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 /* 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, 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 set it and ignore the items. */
and put them into their own record if we have any fields without
rep clauses. */
if (gnu_our_rep_list && p_gnu_rep_list && !all_rep) if (gnu_our_rep_list && p_gnu_rep_list && !all_rep)
*p_gnu_rep_list = chainon (*p_gnu_rep_list, gnu_our_rep_list); *p_gnu_rep_list = chainon (*p_gnu_rep_list, gnu_our_rep_list);
else if (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 tree gnu_rep_type
= (gnu_field_list ? make_node (RECORD_TYPE) : gnu_record_type); = (gnu_field_list ? make_node (RECORD_TYPE) : gnu_record_type);
int len = list_length (gnu_our_rep_list); int len = list_length (gnu_our_rep_list);
tree *gnu_arr = (tree *) alloca (sizeof (tree) * len); tree *gnu_arr = (tree *) alloca (sizeof (tree) * len);
int i; 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; for (i = 0, gnu_field = gnu_our_rep_list; gnu_field;
gnu_field = TREE_CHAIN (gnu_field), i++) gnu_field = TREE_CHAIN (gnu_field), i++)
{ gnu_arr[i] = gnu_field;
gnu_arr[i] = gnu_field;
DECL_FCONTEXT (gnu_field) = size_int (i);
}
qsort (gnu_arr, len, sizeof (tree), compare_field_bitpos); qsort (gnu_arr, len, sizeof (tree), compare_field_bitpos);
...@@ -5708,7 +5717,6 @@ components_to_record (tree gnu_record_type, Node_Id component_list, ...@@ -5708,7 +5717,6 @@ components_to_record (tree gnu_record_type, Node_Id component_list,
TREE_CHAIN (gnu_arr[i]) = gnu_our_rep_list; TREE_CHAIN (gnu_arr[i]) = gnu_our_rep_list;
gnu_our_rep_list = gnu_arr[i]; gnu_our_rep_list = gnu_arr[i];
DECL_CONTEXT (gnu_arr[i]) = gnu_rep_type; DECL_CONTEXT (gnu_arr[i]) = gnu_rep_type;
DECL_FCONTEXT (gnu_arr[i]) = NULL_TREE;
} }
if (gnu_field_list) if (gnu_field_list)
...@@ -5734,7 +5742,8 @@ components_to_record (tree gnu_record_type, Node_Id component_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 /* 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 static int
compare_field_bitpos (const PTR rt1, const PTR rt2) compare_field_bitpos (const PTR rt1, const PTR rt2)
...@@ -5743,9 +5752,7 @@ 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; tree *t2 = (tree *) rt2;
if (tree_int_cst_equal (bit_position (*t1), bit_position (*t2))) if (tree_int_cst_equal (bit_position (*t1), bit_position (*t2)))
return return DECL_UID (*t1) < DECL_UID (*t2) ? -1 : 1;
(tree_int_cst_lt (DECL_FCONTEXT (*t1), DECL_FCONTEXT (*t2))
? -1 : 1);
else if (tree_int_cst_lt (bit_position (*t1), bit_position (*t2))) else if (tree_int_cst_lt (bit_position (*t1), bit_position (*t2)))
return -1; return -1;
else else
......
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