Commit 7194767c by Eric Botcazou Committed by Eric Botcazou

gigi.h (gnat_stabilize_reference): Adjust prototype.

	* gcc-interface/gigi.h (gnat_stabilize_reference): Adjust prototype.
	* gcc-interface/decl.c (gnat_to_gnu_entity): Do not rely on const_flag
 	to detect constant renamings.  Be prepared for specific pattern of
	renamed object based on function calls.  Create a constant object
	for the renaming of a NULL_EXPR or of a CONSTRUCTOR.  Adjust calls
	to gnat_stabilize_reference and tidy up.  Remove redundant tests.
	(elaborate_expression_1): Remove obsolete test and tidy up.
	* gcc-interface/trans.c (Call_to_gnu): Do not stabilize In/Out or Out
	parameters passed by reference.
	(gnat_to_gnu) <N_Selected_Component>: Remove redundant protection again
	side-effects.
	Use gnat_protect_expr instead of gnat_stabilize_reference for general
	protection against side-effects.
	* gcc-interface/utils2.c (gnat_stable_expr_p): New predicate.
	(gnat_save_expr): Invoke it.
	(gnat_protect_expr): Likewise.
	(gnat_stabilize_reference_1): Likewise.  Remove useless propagation
	of TREE_THIS_NOTRAP.
	(gnat_stabilize_reference): Remove parameter and adjust throughout.
	Delete ADDR_EXDR, COMPOUND_EXPR and CONSTRUCTOR cases.
	Restrict CALL_EXPR case to atomic loads and tweak ERROR_MARK case.

From-SVN: r223708
parent 517d07c9
2015-05-26 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/gigi.h (gnat_stabilize_reference): Adjust prototype.
* gcc-interface/decl.c (gnat_to_gnu_entity): Do not rely on const_flag
to detect constant renamings. Be prepared for specific pattern of
renamed object based on function calls. Create a constant object
for the renaming of a NULL_EXPR or of a CONSTRUCTOR. Adjust calls
to gnat_stabilize_reference and tidy up. Remove redundant tests.
(elaborate_expression_1): Remove obsolete test and tidy up.
* gcc-interface/trans.c (Call_to_gnu): Do not stabilize In/Out or Out
parameters passed by reference.
(gnat_to_gnu) <N_Selected_Component>: Remove redundant protection again
side-effects.
Use gnat_protect_expr instead of gnat_stabilize_reference for general
protection against side-effects.
* gcc-interface/utils2.c (gnat_stable_expr_p): New predicate.
(gnat_save_expr): Invoke it.
(gnat_protect_expr): Likewise.
(gnat_stabilize_reference_1): Likewise. Remove useless propagation
of TREE_THIS_NOTRAP.
(gnat_stabilize_reference): Remove parameter and adjust throughout.
Delete ADDR_EXDR, COMPOUND_EXPR and CONSTRUCTOR cases.
Restrict CALL_EXPR case to atomic loads and tweak ERROR_MARK case.
2015-05-26 Ed Schonberg <schonberg@adacore.com> 2015-05-26 Ed Schonberg <schonberg@adacore.com>
* sinfo.ads: Minor reformatting. * sinfo.ads: Minor reformatting.
......
...@@ -965,9 +965,8 @@ extern tree gnat_protect_expr (tree exp); ...@@ -965,9 +965,8 @@ extern tree gnat_protect_expr (tree exp);
/* This is equivalent to stabilize_reference in tree.c but we know how to /* This is equivalent to stabilize_reference in tree.c but we know how to
handle our own nodes and we take extra arguments. FORCE says whether to handle our own nodes and we take extra arguments. FORCE says whether to
force evaluation of everything. We set SUCCESS to true unless we walk force evaluation of everything. */
through something we don't know how to stabilize. */ extern tree gnat_stabilize_reference (tree ref, bool force);
extern tree gnat_stabilize_reference (tree ref, bool force, bool *success);
/* This is equivalent to get_inner_reference in expr.c but it returns the /* This is equivalent to get_inner_reference in expr.c but it returns the
ultimate containing object only if the reference (lvalue) is constant, ultimate containing object only if the reference (lvalue) is constant,
......
...@@ -4241,11 +4241,11 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, ...@@ -4241,11 +4241,11 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
/* If it's possible we may need to use this expression twice, make sure /* If it's possible we may need to use this expression twice, make sure
that any side-effects are handled via SAVE_EXPRs; likewise if we need that any side-effects are handled via SAVE_EXPRs; likewise if we need
to force side-effects before the call. to force side-effects before the call. */
??? This is more conservative than we need since we don't need to do if (Ekind (gnat_formal) != E_In_Parameter
this for pass-by-ref with no conversion. */ && !is_by_ref_formal_parm
if (Ekind (gnat_formal) != E_In_Parameter) && TREE_CODE (gnu_name) != NULL_EXPR)
gnu_name = gnat_stabilize_reference (gnu_name, true, NULL); gnu_name = gnat_stabilize_reference (gnu_name, true);
/* If we are passing a non-addressable parameter by reference, pass the /* If we are passing a non-addressable parameter by reference, pass the
address of a copy. In the Out or In Out case, set up to copy back address of a copy. In the Out or In Out case, set up to copy back
...@@ -6099,14 +6099,6 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -6099,14 +6099,6 @@ gnat_to_gnu (Node_Id gnat_node)
{ {
gnu_field = gnat_to_gnu_field_decl (gnat_field); gnu_field = gnat_to_gnu_field_decl (gnat_field);
/* If there are discriminants, the prefix might be evaluated more
than once, which is a problem if it has side-effects. */
if (Has_Discriminants (Is_Access_Type (Etype (Prefix (gnat_node)))
? Designated_Type (Etype
(Prefix (gnat_node)))
: Etype (Prefix (gnat_node))))
gnu_prefix = gnat_stabilize_reference (gnu_prefix, false, NULL);
gnu_result gnu_result
= build_component_ref (gnu_prefix, NULL_TREE, gnu_field, = build_component_ref (gnu_prefix, NULL_TREE, gnu_field,
(Nkind (Parent (gnat_node)) (Nkind (Parent (gnat_node))
...@@ -7313,7 +7305,6 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -7313,7 +7305,6 @@ gnat_to_gnu (Node_Id gnat_node)
gets inserted there as well. This ensures that the type elaboration gets inserted there as well. This ensures that the type elaboration
code is issued past the actions computing values on which it might code is issued past the actions computing values on which it might
depend. */ depend. */
start_stmt_group (); start_stmt_group ();
add_stmt_list (Actions (gnat_node)); add_stmt_list (Actions (gnat_node));
gnu_expr = gnat_to_gnu (Expression (gnat_node)); gnu_expr = gnat_to_gnu (Expression (gnat_node));
...@@ -7498,7 +7489,7 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -7498,7 +7489,7 @@ gnat_to_gnu (Node_Id gnat_node)
&& TYPE_IS_PADDING_P (TREE_TYPE (gnu_result))) && TYPE_IS_PADDING_P (TREE_TYPE (gnu_result)))
&& (TREE_CODE (gnu_result_type) == UNCONSTRAINED_ARRAY_TYPE && (TREE_CODE (gnu_result_type) == UNCONSTRAINED_ARRAY_TYPE
|| CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_result_type)))) || CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_result_type))))
gnu_result = gnat_stabilize_reference (gnu_result, false, NULL); gnu_result = gnat_protect_expr (gnu_result);
/* Now convert the result to the result type, unless we are in one of the /* Now convert the result to the result type, unless we are in one of the
following cases: following cases:
......
...@@ -2563,6 +2563,17 @@ gnat_mark_addressable (tree t) ...@@ -2563,6 +2563,17 @@ gnat_mark_addressable (tree t)
} }
} }
/* Return true if EXP is a stable expression for the purpose of the functions
below and, therefore, can be returned unmodified by them. We accept things
that are actual constants or that have already been handled. */
static bool
gnat_stable_expr_p (tree exp)
{
enum tree_code code = TREE_CODE (exp);
return TREE_CONSTANT (exp) || code == NULL_EXPR || code == SAVE_EXPR;
}
/* Save EXP for later use or reuse. This is equivalent to save_expr in tree.c /* Save EXP for later use or reuse. This is equivalent to save_expr in tree.c
but we know how to handle our own nodes. */ but we know how to handle our own nodes. */
...@@ -2572,7 +2583,7 @@ gnat_save_expr (tree exp) ...@@ -2572,7 +2583,7 @@ gnat_save_expr (tree exp)
tree type = TREE_TYPE (exp); tree type = TREE_TYPE (exp);
enum tree_code code = TREE_CODE (exp); enum tree_code code = TREE_CODE (exp);
if (TREE_CONSTANT (exp) || code == SAVE_EXPR || code == NULL_EXPR) if (gnat_stable_expr_p (exp))
return exp; return exp;
if (code == UNCONSTRAINED_ARRAY_REF) if (code == UNCONSTRAINED_ARRAY_REF)
...@@ -2603,7 +2614,7 @@ gnat_protect_expr (tree exp) ...@@ -2603,7 +2614,7 @@ gnat_protect_expr (tree exp)
tree type = TREE_TYPE (exp); tree type = TREE_TYPE (exp);
enum tree_code code = TREE_CODE (exp); enum tree_code code = TREE_CODE (exp);
if (TREE_CONSTANT (exp) || code == SAVE_EXPR || code == NULL_EXPR) if (gnat_stable_expr_p (exp))
return exp; return exp;
/* If EXP has no side effects, we theoretically don't need to do anything. /* If EXP has no side effects, we theoretically don't need to do anything.
...@@ -2669,11 +2680,7 @@ gnat_stabilize_reference_1 (tree e, bool force) ...@@ -2669,11 +2680,7 @@ gnat_stabilize_reference_1 (tree e, bool force)
tree type = TREE_TYPE (e); tree type = TREE_TYPE (e);
tree result; tree result;
/* We cannot ignore const expressions because it might be a reference if (gnat_stable_expr_p (e))
to a const array but whose index contains side-effects. But we can
ignore things that are actual constant or that already have been
handled by this function. */
if (TREE_CONSTANT (e) || code == SAVE_EXPR)
return e; return e;
switch (TREE_CODE_CLASS (code)) switch (TREE_CODE_CLASS (code))
...@@ -2722,36 +2729,24 @@ gnat_stabilize_reference_1 (tree e, bool force) ...@@ -2722,36 +2729,24 @@ gnat_stabilize_reference_1 (tree e, bool force)
gcc_unreachable (); gcc_unreachable ();
} }
/* See similar handling in gnat_stabilize_reference. */
TREE_READONLY (result) = TREE_READONLY (e); TREE_READONLY (result) = TREE_READONLY (e);
TREE_SIDE_EFFECTS (result) |= TREE_SIDE_EFFECTS (e); TREE_SIDE_EFFECTS (result) |= TREE_SIDE_EFFECTS (e);
TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e); TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);
if (code == INDIRECT_REF
|| code == UNCONSTRAINED_ARRAY_REF
|| code == ARRAY_REF
|| code == ARRAY_RANGE_REF)
TREE_THIS_NOTRAP (result) = TREE_THIS_NOTRAP (e);
return result; return result;
} }
/* This is equivalent to stabilize_reference in tree.c but we know how to /* This is equivalent to stabilize_reference in tree.c but we know how to
handle our own nodes and we take extra arguments. FORCE says whether to handle our own nodes and we take extra arguments. FORCE says whether to
force evaluation of everything. We set SUCCESS to true unless we walk force evaluation of everything. */
through something we don't know how to stabilize. */
tree tree
gnat_stabilize_reference (tree ref, bool force, bool *success) gnat_stabilize_reference (tree ref, bool force)
{ {
tree type = TREE_TYPE (ref); tree type = TREE_TYPE (ref);
enum tree_code code = TREE_CODE (ref); enum tree_code code = TREE_CODE (ref);
tree result; tree result;
/* Assume we'll success unless proven otherwise. */
if (success)
*success = true;
switch (code) switch (code)
{ {
case CONST_DECL: case CONST_DECL:
...@@ -2761,15 +2756,13 @@ gnat_stabilize_reference (tree ref, bool force, bool *success) ...@@ -2761,15 +2756,13 @@ gnat_stabilize_reference (tree ref, bool force, bool *success)
/* No action is needed in this case. */ /* No action is needed in this case. */
return ref; return ref;
case ADDR_EXPR:
CASE_CONVERT: CASE_CONVERT:
case FLOAT_EXPR: case FLOAT_EXPR:
case FIX_TRUNC_EXPR: case FIX_TRUNC_EXPR:
case VIEW_CONVERT_EXPR: case VIEW_CONVERT_EXPR:
result result
= build1 (code, type, = build1 (code, type,
gnat_stabilize_reference (TREE_OPERAND (ref, 0), force, gnat_stabilize_reference (TREE_OPERAND (ref, 0), force));
success));
break; break;
case INDIRECT_REF: case INDIRECT_REF:
...@@ -2781,79 +2774,51 @@ gnat_stabilize_reference (tree ref, bool force, bool *success) ...@@ -2781,79 +2774,51 @@ gnat_stabilize_reference (tree ref, bool force, bool *success)
case COMPONENT_REF: case COMPONENT_REF:
result = build3 (COMPONENT_REF, type, result = build3 (COMPONENT_REF, type,
gnat_stabilize_reference (TREE_OPERAND (ref, 0), force, gnat_stabilize_reference (TREE_OPERAND (ref, 0), force),
success),
TREE_OPERAND (ref, 1), NULL_TREE); TREE_OPERAND (ref, 1), NULL_TREE);
break; break;
case BIT_FIELD_REF: case BIT_FIELD_REF:
result = build3 (BIT_FIELD_REF, type, result = build3 (BIT_FIELD_REF, type,
gnat_stabilize_reference (TREE_OPERAND (ref, 0), force, gnat_stabilize_reference (TREE_OPERAND (ref, 0), force),
success),
TREE_OPERAND (ref, 1), TREE_OPERAND (ref, 2)); TREE_OPERAND (ref, 1), TREE_OPERAND (ref, 2));
break; break;
case ARRAY_REF: case ARRAY_REF:
case ARRAY_RANGE_REF: case ARRAY_RANGE_REF:
result = build4 (code, type, result
gnat_stabilize_reference (TREE_OPERAND (ref, 0), force, = build4 (code, type,
success), gnat_stabilize_reference (TREE_OPERAND (ref, 0), force),
gnat_stabilize_reference_1 (TREE_OPERAND (ref, 1), gnat_stabilize_reference_1 (TREE_OPERAND (ref, 1), force),
force), TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3));
NULL_TREE, NULL_TREE);
break; break;
case CALL_EXPR: case CALL_EXPR:
if (call_is_atomic_load (ref)) {
result /* This can only be an atomic load. */
= build_call_expr (TREE_OPERAND (CALL_EXPR_FN (ref), 0), 2, gcc_assert (call_is_atomic_load (ref));
gnat_stabilize_reference (CALL_EXPR_ARG (ref, 0),
force, success), /* An atomic load is an INDIRECT_REF of its first argument. */
CALL_EXPR_ARG (ref, 1)); tree t = CALL_EXPR_ARG (ref, 0);
else if (TREE_CODE (t) == NOP_EXPR)
result = gnat_stabilize_reference_1 (ref, force); t = TREE_OPERAND (t, 0);
break; if (TREE_CODE (t) == ADDR_EXPR)
t = build1 (ADDR_EXPR, TREE_TYPE (t),
case COMPOUND_EXPR: gnat_stabilize_reference (TREE_OPERAND (t, 0), force));
result = build2 (COMPOUND_EXPR, type, else
gnat_stabilize_reference (TREE_OPERAND (ref, 0), force, t = gnat_stabilize_reference_1 (t, force);
success), t = fold_convert (TREE_TYPE (CALL_EXPR_ARG (ref, 0)), t);
gnat_stabilize_reference (TREE_OPERAND (ref, 1), force,
success));
break;
case CONSTRUCTOR: result = build_call_expr (TREE_OPERAND (CALL_EXPR_FN (ref), 0), 2,
/* Constructors with 1 element are used extensively to formally t, CALL_EXPR_ARG (ref, 1));
convert objects to special wrapping types. */ }
if (TREE_CODE (type) == RECORD_TYPE
&& vec_safe_length (CONSTRUCTOR_ELTS (ref)) == 1)
{
tree index = (*CONSTRUCTOR_ELTS (ref))[0].index;
tree value = (*CONSTRUCTOR_ELTS (ref))[0].value;
result
= build_constructor_single (type, index,
gnat_stabilize_reference_1 (value,
force));
}
else
{
if (success)
*success = false;
return ref;
}
break; break;
case ERROR_MARK: case ERROR_MARK:
ref = error_mark_node; return error_mark_node;
/* ... fall through to failure ... */
/* If arg isn't a kind of lvalue we recognize, make no change.
Caller should recognize the error for an invalid lvalue. */
default: default:
if (success) gcc_unreachable ();
*success = false;
return ref;
} }
/* TREE_THIS_VOLATILE and TREE_SIDE_EFFECTS set on the initial expression /* TREE_THIS_VOLATILE and TREE_SIDE_EFFECTS set on the initial expression
......
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