Commit 241125b2 by Eric Botcazou Committed by Eric Botcazou

ada-tree.h (DECL_GLOBAL_NONCONSTANT_RENAMING_P): Delete

	* gcc-interface/ada-tree.h (DECL_GLOBAL_NONCONSTANT_RENAMING_P): Delete
	(DECL_RENAMED_OBJECT): Adjust comment.
	* gcc-interface/gigi.h (record_global_nonconstant_renaming): Delete.
	(invalidate_global_nonconstant_renamings): Likewise.
	(gnat_constant_reference_p): Likewise.
	(rewrite_fn): New function type.
	(gnat_rewrite_reference): Declare.
	(call_is_atomic_load): New inline predicate.
	* gcc-interface/decl.c (elaborate_reference_1): New function.
	(elaborate_reference): Likewise.
	(gnat_to_gnu_entity): Call elaborate_reference to elaborate renamings
	and simplify associated code.  Set const_flag to true consistently in
 	conjunction with used_by_ref.
	* gcc-interface/trans.c (Identifier_to_gnu): Always replace renaming
	pointers by renamed objects.
	(outer_atomic_access_required_p): Deal with renamings.
	(Compilation_Unit_to_gnu): Do not call
	invalidate_global_nonconstant_renamings.
	(gnat_to_gnu) <N_Object_Renaming_Declaration>: Adjust comment.
	(gnat_gimplify_expr): Deal with atomic loads.
	* gcc-interface/utils.c (global_nonconstant_renamings): Delete.
	(destroy_gnat_utils): Do not call
	invalidate_global_nonconstant_renamings.
	(record_global_nonconstant_renaming): Delete.
	(invalidate_global_nonconstant_renamings): Likewise.
	* gcc-interface/utils2.c (call_is_atomic_load): Move to gigi.h.
	(build_load_modify_store): Build a copy of the destination.
	(gnat_stabilize_reference_1): Adjust.
	(gnat_stabilize_reference): Call gnat_stabilize_reference_1 through
	gnat_rewrite_reference and move bulk of code to...
	(gnat_rewrite_reference): ...here.  New global function.
	(gnat_constant_reference_p): Delete.

From-SVN: r223709
parent 7194767c
2015-05-26 Eric Botcazou <ebotcazou@adacore.com> 2015-05-26 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/ada-tree.h (DECL_GLOBAL_NONCONSTANT_RENAMING_P): Delete
(DECL_RENAMED_OBJECT): Adjust comment.
* gcc-interface/gigi.h (record_global_nonconstant_renaming): Delete.
(invalidate_global_nonconstant_renamings): Likewise.
(gnat_constant_reference_p): Likewise.
(rewrite_fn): New function type.
(gnat_rewrite_reference): Declare.
(call_is_atomic_load): New inline predicate.
* gcc-interface/decl.c (elaborate_reference_1): New function.
(elaborate_reference): Likewise.
(gnat_to_gnu_entity): Call elaborate_reference to elaborate renamings
and simplify associated code. Set const_flag to true consistently in
conjunction with used_by_ref.
* gcc-interface/trans.c (Identifier_to_gnu): Always replace renaming
pointers by renamed objects.
(outer_atomic_access_required_p): Deal with renamings.
(Compilation_Unit_to_gnu): Do not call
invalidate_global_nonconstant_renamings.
(gnat_to_gnu) <N_Object_Renaming_Declaration>: Adjust comment.
(gnat_gimplify_expr): Deal with atomic loads.
* gcc-interface/utils.c (global_nonconstant_renamings): Delete.
(destroy_gnat_utils): Do not call
invalidate_global_nonconstant_renamings.
(record_global_nonconstant_renaming): Delete.
(invalidate_global_nonconstant_renamings): Likewise.
* gcc-interface/utils2.c (call_is_atomic_load): Move to gigi.h.
(build_load_modify_store): Build a copy of the destination.
(gnat_stabilize_reference_1): Adjust.
(gnat_stabilize_reference): Call gnat_stabilize_reference_1 through
gnat_rewrite_reference and move bulk of code to...
(gnat_rewrite_reference): ...here. New global function.
(gnat_constant_reference_p): Delete.
2015-05-26 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/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 * gcc-interface/decl.c (gnat_to_gnu_entity): Do not rely on const_flag
to detect constant renamings. Be prepared for specific pattern of to detect constant renamings. Be prepared for specific pattern of
......
...@@ -394,10 +394,6 @@ do { \ ...@@ -394,10 +394,6 @@ do { \
is readonly. */ is readonly. */
#define DECL_POINTS_TO_READONLY_P(NODE) DECL_LANG_FLAG_4 (NODE) #define DECL_POINTS_TO_READONLY_P(NODE) DECL_LANG_FLAG_4 (NODE)
/* Nonzero in a VAR_DECL if it is a global non-constant renaming. */
#define DECL_GLOBAL_NONCONSTANT_RENAMING_P(NODE) \
DECL_LANG_FLAG_5 (VAR_DECL_CHECK (NODE))
/* In a FIELD_DECL corresponding to a discriminant, contains the /* In a FIELD_DECL corresponding to a discriminant, contains the
discriminant number. */ discriminant number. */
#define DECL_DISCRIMINANT_NUMBER(NODE) DECL_INITIAL (FIELD_DECL_CHECK (NODE)) #define DECL_DISCRIMINANT_NUMBER(NODE) DECL_INITIAL (FIELD_DECL_CHECK (NODE))
...@@ -439,8 +435,7 @@ do { \ ...@@ -439,8 +435,7 @@ do { \
SET_DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE), X) SET_DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE), X)
/* In a VAR_DECL without the DECL_LOOP_PARM_P flag set and that is a renaming /* In a VAR_DECL without the DECL_LOOP_PARM_P flag set and that is a renaming
pointer, points to the object being renamed, if any. Note that this object pointer, points to the object being renamed, if any. */
is guaranteed to be protected against multiple evaluations. */
#define DECL_RENAMED_OBJECT(NODE) \ #define DECL_RENAMED_OBJECT(NODE) \
GET_DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE)) GET_DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))
#define SET_DECL_RENAMED_OBJECT(NODE, X) \ #define SET_DECL_RENAMED_OBJECT(NODE, X) \
......
...@@ -712,12 +712,6 @@ create_var_decl_1 (tree var_name, tree asm_name, tree type, tree var_init, ...@@ -712,12 +712,6 @@ create_var_decl_1 (tree var_name, tree asm_name, tree type, tree var_init,
const_flag, public_flag, extern_flag, \ const_flag, public_flag, extern_flag, \
static_flag, false, attr_list, gnat_node) static_flag, false, attr_list, gnat_node)
/* Record DECL as a global non-constant renaming. */
extern void record_global_nonconstant_renaming (tree decl);
/* Invalidate the global non-constant renamings. */
extern void invalidate_global_nonconstant_renamings (void);
/* Return a FIELD_DECL node. FIELD_NAME is the field's name, FIELD_TYPE is /* Return a FIELD_DECL node. FIELD_NAME is the field's name, FIELD_TYPE is
its type and RECORD_TYPE is the type of the enclosing record. If SIZE is its type and RECORD_TYPE is the type of the enclosing record. If SIZE is
nonzero, it is the specified size of the field. If POS is nonzero, it is nonzero, it is the specified size of the field. If POS is nonzero, it is
...@@ -968,15 +962,19 @@ extern tree gnat_protect_expr (tree exp); ...@@ -968,15 +962,19 @@ extern tree gnat_protect_expr (tree exp);
force evaluation of everything. */ force evaluation of everything. */
extern tree gnat_stabilize_reference (tree ref, bool force); extern tree gnat_stabilize_reference (tree ref, bool force);
/* Rewrite reference REF and call FUNC on each expression within REF in the
process. DATA is passed unmodified to FUNC and N is bumped each time it
is passed to FUNC, so FUNC is guaranteed to see a given N only once per
reference to be rewritten. */
typedef tree (*rewrite_fn) (tree, void *, int);
extern tree gnat_rewrite_reference (tree ref, rewrite_fn func, void *data,
int n = 1);
/* 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,
i.e. if it doesn't depend on the context in which it is evaluated. */ i.e. if it doesn't depend on the context in which it is evaluated. */
extern tree get_inner_constant_reference (tree exp); extern tree get_inner_constant_reference (tree exp);
/* Return true if REF is a constant reference, i.e. a reference (lvalue) that
doesn't depend on the context in which it is evaluated. */
extern bool gnat_constant_reference_p (tree ref);
/* If EXPR is an expression that is invariant in the current function, in the /* If EXPR is an expression that is invariant in the current function, in the
sense that it can be evaluated anywhere in the function and any number of sense that it can be evaluated anywhere in the function and any number of
times, return EXPR or an equivalent expression. Otherwise return NULL. */ times, return EXPR or an equivalent expression. Otherwise return NULL. */
...@@ -1073,3 +1071,17 @@ ceil_pow2 (unsigned HOST_WIDE_INT x) ...@@ -1073,3 +1071,17 @@ ceil_pow2 (unsigned HOST_WIDE_INT x)
{ {
return (unsigned HOST_WIDE_INT) 1 << (floor_log2 (x - 1) + 1); return (unsigned HOST_WIDE_INT) 1 << (floor_log2 (x - 1) + 1);
} }
/* Return true if EXP, a CALL_EXPR, is an atomic load. */
static inline bool
call_is_atomic_load (tree exp)
{
tree fndecl = get_callee_fndecl (exp);
if (!(fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL))
return false;
enum built_in_function code = DECL_FUNCTION_CODE (fndecl);
return BUILT_IN_ATOMIC_LOAD_N <= code && code <= BUILT_IN_ATOMIC_LOAD_16;
}
...@@ -1163,15 +1163,10 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p) ...@@ -1163,15 +1163,10 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
true, false))) true, false)))
gnu_result = DECL_INITIAL (gnu_result); gnu_result = DECL_INITIAL (gnu_result);
/* If it's a renaming pointer and not a global non-constant renaming or /* If it's a renaming pointer, get to the renamed object. */
we are at the global level, the we can reference the renamed object
directly, since it is either constant or has been protected against
multiple evaluations. */
if (TREE_CODE (gnu_result) == VAR_DECL if (TREE_CODE (gnu_result) == VAR_DECL
&& !DECL_LOOP_PARM_P (gnu_result) && !DECL_LOOP_PARM_P (gnu_result)
&& DECL_RENAMED_OBJECT (gnu_result) && DECL_RENAMED_OBJECT (gnu_result))
&& (!DECL_GLOBAL_NONCONSTANT_RENAMING_P (gnu_result)
|| global_bindings_p ()))
gnu_result = DECL_RENAMED_OBJECT (gnu_result); gnu_result = DECL_RENAMED_OBJECT (gnu_result);
/* Otherwise, do the final dereference. */ /* Otherwise, do the final dereference. */
...@@ -3975,16 +3970,32 @@ outer_atomic_access_required_p (Node_Id gnat_node) ...@@ -3975,16 +3970,32 @@ outer_atomic_access_required_p (Node_Id gnat_node)
{ {
gnat_node = gnat_strip_type_conversion (gnat_node); gnat_node = gnat_strip_type_conversion (gnat_node);
while (Nkind (gnat_node) == N_Indexed_Component while (true)
|| Nkind (gnat_node) == N_Selected_Component
|| Nkind (gnat_node) == N_Slice)
{ {
gnat_node = gnat_strip_type_conversion (Prefix (gnat_node)); switch (Nkind (gnat_node))
if (node_has_volatile_full_access (gnat_node)) {
return true; case N_Identifier:
case N_Expanded_Name:
if (No (Renamed_Object (Entity (gnat_node))))
return false;
gnat_node
= gnat_strip_type_conversion (Renamed_Object (Entity (gnat_node)));
break;
case N_Indexed_Component:
case N_Selected_Component:
case N_Slice:
gnat_node = gnat_strip_type_conversion (Prefix (gnat_node));
if (node_has_volatile_full_access (gnat_node))
return true;
break;
default:
return false;
}
} }
return false; gcc_unreachable ();
} }
/* Return true if GNAT_NODE requires atomic access and set SYNC according to /* Return true if GNAT_NODE requires atomic access and set SYNC according to
...@@ -5290,11 +5301,6 @@ Compilation_Unit_to_gnu (Node_Id gnat_node) ...@@ -5290,11 +5301,6 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
info->gnat_node = gnat_node; info->gnat_node = gnat_node;
elab_info_list = info; elab_info_list = info;
/* Invalidate the global non-constant renamings. This is necessary because
stabilization of the renamed entities may create SAVE_EXPRs which have
been tied to a specific elaboration routine just above. */
invalidate_global_nonconstant_renamings ();
/* Force the processing for all nodes that remain in the queue. */ /* Force the processing for all nodes that remain in the queue. */
process_deferred_decl_context (true); process_deferred_decl_context (true);
} }
...@@ -5838,8 +5844,7 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -5838,8 +5844,7 @@ gnat_to_gnu (Node_Id gnat_node)
tree gnu_temp tree gnu_temp
= gnat_to_gnu_entity (gnat_temp, = gnat_to_gnu_entity (gnat_temp,
gnat_to_gnu (Renamed_Object (gnat_temp)), 1); gnat_to_gnu (Renamed_Object (gnat_temp)), 1);
/* We need to make sure that the side-effects of the renamed object /* See case 2 of renaming in gnat_to_gnu_entity. */
are evaluated at this point, so we evaluate its address. */
if (TREE_SIDE_EFFECTS (gnu_temp)) if (TREE_SIDE_EFFECTS (gnu_temp))
gnu_result = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_temp); gnu_result = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_temp);
} }
...@@ -7933,6 +7938,26 @@ gnat_gimplify_expr (tree *expr_p, gimple_seq *pre_p, ...@@ -7933,6 +7938,26 @@ gnat_gimplify_expr (tree *expr_p, gimple_seq *pre_p,
return GS_ALL_DONE; return GS_ALL_DONE;
} }
/* Replace atomic loads with their first argument. That's necessary
because the gimplifier would create a temporary otherwise. */
if (TREE_SIDE_EFFECTS (op))
while (handled_component_p (op) || CONVERT_EXPR_P (op))
{
tree inner = TREE_OPERAND (op, 0);
if (TREE_CODE (inner) == CALL_EXPR && call_is_atomic_load (inner))
{
tree t = CALL_EXPR_ARG (inner, 0);
if (TREE_CODE (t) == NOP_EXPR)
t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == ADDR_EXPR)
TREE_OPERAND (op, 0) = TREE_OPERAND (t, 0);
else
TREE_OPERAND (op, 0) = build_fold_indirect_ref (t);
}
else
op = inner;
}
return GS_UNHANDLED; return GS_UNHANDLED;
case VIEW_CONVERT_EXPR: case VIEW_CONVERT_EXPR:
......
...@@ -233,9 +233,6 @@ static GTY(()) vec<tree, va_gc> *global_decls; ...@@ -233,9 +233,6 @@ static GTY(()) vec<tree, va_gc> *global_decls;
/* An array of builtin function declarations. */ /* An array of builtin function declarations. */
static GTY(()) vec<tree, va_gc> *builtin_decls; static GTY(()) vec<tree, va_gc> *builtin_decls;
/* An array of global non-constant renamings. */
static GTY(()) vec<tree, va_gc> *global_nonconstant_renamings;
/* A chain of unused BLOCK nodes. */ /* A chain of unused BLOCK nodes. */
static GTY((deletable)) tree free_block_chain; static GTY((deletable)) tree free_block_chain;
...@@ -322,9 +319,6 @@ destroy_gnat_utils (void) ...@@ -322,9 +319,6 @@ destroy_gnat_utils (void)
/* Destroy the hash table of padded types. */ /* Destroy the hash table of padded types. */
pad_type_hash_table->empty (); pad_type_hash_table->empty ();
pad_type_hash_table = NULL; pad_type_hash_table = NULL;
/* Invalidate the global non-constant renamings. */
invalidate_global_nonconstant_renamings ();
} }
/* GNAT_ENTITY is a GNAT tree node for an entity. Associate GNU_DECL, a GCC /* GNAT_ENTITY is a GNAT tree node for an entity. Associate GNU_DECL, a GCC
...@@ -2717,33 +2711,6 @@ process_attributes (tree *node, struct attrib **attr_list, bool in_place, ...@@ -2717,33 +2711,6 @@ process_attributes (tree *node, struct attrib **attr_list, bool in_place,
*attr_list = NULL; *attr_list = NULL;
} }
/* Record DECL as a global non-constant renaming. */
void
record_global_nonconstant_renaming (tree decl)
{
gcc_assert (!DECL_LOOP_PARM_P (decl) && DECL_RENAMED_OBJECT (decl));
vec_safe_push (global_nonconstant_renamings, decl);
}
/* Invalidate the global non-constant renamings, lest their renamed object
contains SAVE_EXPRs tied to an elaboration routine. */
void
invalidate_global_nonconstant_renamings (void)
{
unsigned int i;
tree iter;
if (global_nonconstant_renamings == NULL)
return;
FOR_EACH_VEC_ELT (*global_nonconstant_renamings, i, iter)
SET_DECL_RENAMED_OBJECT (iter, NULL_TREE);
vec_free (global_nonconstant_renamings);
}
/* Return true if VALUE is a known to be a multiple of FACTOR, which must be /* Return true if VALUE is a known to be a multiple of FACTOR, which must be
a power of 2. */ a power of 2. */
......
...@@ -738,27 +738,15 @@ build_atomic_store (tree dest, tree src, bool sync) ...@@ -738,27 +738,15 @@ build_atomic_store (tree dest, tree src, bool sync)
return build_call_expr (t, 3, addr, src, mem_model); return build_call_expr (t, 3, addr, src, mem_model);
} }
/* Return true if EXP, a CALL_EXPR, is an atomic load. */
static bool
call_is_atomic_load (tree exp)
{
tree fndecl = get_callee_fndecl (exp);
if (!(fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL))
return false;
enum built_in_function code = DECL_FUNCTION_CODE (fndecl);
return BUILT_IN_ATOMIC_LOAD_N <= code && code <= BUILT_IN_ATOMIC_LOAD_16;
}
/* Build a load-modify-store sequence from SRC to DEST. GNAT_NODE is used for /* Build a load-modify-store sequence from SRC to DEST. GNAT_NODE is used for
the location of the sequence. Note that, even if the load and the store are the location of the sequence. Note that, even though the load and the store
both atomic, the sequence itself is not atomic. */ are both atomic, the sequence itself is not atomic. */
tree tree
build_load_modify_store (tree dest, tree src, Node_Id gnat_node) build_load_modify_store (tree dest, tree src, Node_Id gnat_node)
{ {
/* We will be modifying DEST below so we build a copy. */
dest = copy_node (dest);
tree ref = dest; tree ref = dest;
while (handled_component_p (ref)) while (handled_component_p (ref))
...@@ -812,6 +800,7 @@ build_load_modify_store (tree dest, tree src, Node_Id gnat_node) ...@@ -812,6 +800,7 @@ build_load_modify_store (tree dest, tree src, Node_Id gnat_node)
} }
} }
TREE_OPERAND (ref, 0) = copy_node (TREE_OPERAND (ref, 0));
ref = TREE_OPERAND (ref, 0); ref = TREE_OPERAND (ref, 0);
} }
...@@ -2674,8 +2663,9 @@ gnat_protect_expr (tree exp) ...@@ -2674,8 +2663,9 @@ gnat_protect_expr (tree exp)
argument to force evaluation of everything. */ argument to force evaluation of everything. */
static tree static tree
gnat_stabilize_reference_1 (tree e, bool force) gnat_stabilize_reference_1 (tree e, void *data, int n)
{ {
const bool force = *(bool *)data;
enum tree_code code = TREE_CODE (e); enum tree_code code = TREE_CODE (e);
tree type = TREE_TYPE (e); tree type = TREE_TYPE (e);
tree result; tree result;
...@@ -2698,7 +2688,7 @@ gnat_stabilize_reference_1 (tree e, bool force) ...@@ -2698,7 +2688,7 @@ gnat_stabilize_reference_1 (tree e, bool force)
&& TYPE_IS_FAT_POINTER_P (TREE_TYPE (TREE_OPERAND (e, 0)))) && TYPE_IS_FAT_POINTER_P (TREE_TYPE (TREE_OPERAND (e, 0))))
result result
= build3 (code, type, = build3 (code, type,
gnat_stabilize_reference_1 (TREE_OPERAND (e, 0), force), gnat_stabilize_reference_1 (TREE_OPERAND (e, 0), data, n),
TREE_OPERAND (e, 1), TREE_OPERAND (e, 2)); TREE_OPERAND (e, 1), TREE_OPERAND (e, 2));
/* If the expression has side-effects, then encase it in a SAVE_EXPR /* If the expression has side-effects, then encase it in a SAVE_EXPR
so that it will only be evaluated once. */ so that it will only be evaluated once. */
...@@ -2714,15 +2704,15 @@ gnat_stabilize_reference_1 (tree e, bool force) ...@@ -2714,15 +2704,15 @@ gnat_stabilize_reference_1 (tree e, bool force)
/* Recursively stabilize each operand. */ /* Recursively stabilize each operand. */
result result
= build2 (code, type, = build2 (code, type,
gnat_stabilize_reference_1 (TREE_OPERAND (e, 0), force), gnat_stabilize_reference_1 (TREE_OPERAND (e, 0), data, n),
gnat_stabilize_reference_1 (TREE_OPERAND (e, 1), force)); gnat_stabilize_reference_1 (TREE_OPERAND (e, 1), data, n));
break; break;
case tcc_unary: case tcc_unary:
/* Recursively stabilize each operand. */ /* Recursively stabilize each operand. */
result result
= build1 (code, type, = build1 (code, type,
gnat_stabilize_reference_1 (TREE_OPERAND (e, 0), force)); gnat_stabilize_reference_1 (TREE_OPERAND (e, 0), data, n));
break; break;
default: default:
...@@ -2743,6 +2733,17 @@ gnat_stabilize_reference_1 (tree e, bool force) ...@@ -2743,6 +2733,17 @@ gnat_stabilize_reference_1 (tree e, bool force)
tree tree
gnat_stabilize_reference (tree ref, bool force) gnat_stabilize_reference (tree ref, bool force)
{ {
return gnat_rewrite_reference (ref, gnat_stabilize_reference_1, &force);
}
/* Rewrite reference REF and call FUNC on each expression within REF in the
process. DATA is passed unmodified to FUNC and N is bumped each time it
is passed to FUNC, so FUNC is guaranteed to see a given N only once per
reference to be rewritten. */
tree
gnat_rewrite_reference (tree ref, rewrite_fn func, void *data, int n)
{
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;
...@@ -2762,25 +2763,26 @@ gnat_stabilize_reference (tree ref, bool force) ...@@ -2762,25 +2763,26 @@ gnat_stabilize_reference (tree ref, bool force)
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_rewrite_reference (TREE_OPERAND (ref, 0), func, data,
n));
break; break;
case INDIRECT_REF: case INDIRECT_REF:
case UNCONSTRAINED_ARRAY_REF: case UNCONSTRAINED_ARRAY_REF:
result = build1 (code, type, result = build1 (code, type, func (TREE_OPERAND (ref, 0), data, n));
gnat_stabilize_reference_1 (TREE_OPERAND (ref, 0),
force));
break; break;
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_rewrite_reference (TREE_OPERAND (ref, 0), func,
data, n),
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_rewrite_reference (TREE_OPERAND (ref, 0), func,
data, n),
TREE_OPERAND (ref, 1), TREE_OPERAND (ref, 2)); TREE_OPERAND (ref, 1), TREE_OPERAND (ref, 2));
break; break;
...@@ -2788,8 +2790,9 @@ gnat_stabilize_reference (tree ref, bool force) ...@@ -2788,8 +2790,9 @@ gnat_stabilize_reference (tree ref, bool force)
case ARRAY_RANGE_REF: case ARRAY_RANGE_REF:
result result
= build4 (code, type, = build4 (code, type,
gnat_stabilize_reference (TREE_OPERAND (ref, 0), force), gnat_rewrite_reference (TREE_OPERAND (ref, 0), func, data,
gnat_stabilize_reference_1 (TREE_OPERAND (ref, 1), force), n + 1),
func (TREE_OPERAND (ref, 1), data, n),
TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3)); TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3));
break; break;
...@@ -2804,9 +2807,10 @@ gnat_stabilize_reference (tree ref, bool force) ...@@ -2804,9 +2807,10 @@ gnat_stabilize_reference (tree ref, bool force)
t = TREE_OPERAND (t, 0); t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == ADDR_EXPR) if (TREE_CODE (t) == ADDR_EXPR)
t = build1 (ADDR_EXPR, TREE_TYPE (t), t = build1 (ADDR_EXPR, TREE_TYPE (t),
gnat_stabilize_reference (TREE_OPERAND (t, 0), force)); gnat_rewrite_reference (TREE_OPERAND (t, 0), func, data,
n));
else else
t = gnat_stabilize_reference_1 (t, force); t = func (t, data, n);
t = fold_convert (TREE_TYPE (CALL_EXPR_ARG (ref, 0)), t); t = fold_convert (TREE_TYPE (CALL_EXPR_ARG (ref, 0)), t);
result = build_call_expr (TREE_OPERAND (CALL_EXPR_FN (ref), 0), 2, result = build_call_expr (TREE_OPERAND (CALL_EXPR_FN (ref), 0), 2,
...@@ -2895,22 +2899,6 @@ done: ...@@ -2895,22 +2899,6 @@ done:
return exp; return exp;
} }
/* Return true if REF is a constant reference, i.e. a reference (lvalue) that
doesn't depend on the context in which it is evaluated. */
bool
gnat_constant_reference_p (tree ref)
{
if (handled_component_p (ref))
{
ref = get_inner_constant_reference (ref);
if (!ref)
return false;
}
return DECL_P (ref);
}
/* If EXPR is an expression that is invariant in the current function, in the /* If EXPR is an expression that is invariant in the current function, in the
sense that it can be evaluated anywhere in the function and any number of sense that it can be evaluated anywhere in the function and any number of
times, return EXPR or an equivalent expression. Otherwise return NULL. */ times, return EXPR or an equivalent expression. Otherwise return NULL. */
......
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