diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2015-05-26 19:40:18 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2015-05-26 19:40:18 +0000 |
commit | 241125b2a1e4d1a694cd54c20ce2d7d5304448b3 (patch) | |
tree | 327efcc70b8f4f364b4effa1ab951f534b11e419 /gcc/ada/gcc-interface/decl.c | |
parent | 7194767cdf77212e8c736f41b426e3f636f52ca3 (diff) | |
download | gcc-241125b2a1e4d1a694cd54c20ce2d7d5304448b3.zip gcc-241125b2a1e4d1a694cd54c20ce2d7d5304448b3.tar.gz gcc-241125b2a1e4d1a694cd54c20ce2d7d5304448b3.tar.bz2 |
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
Diffstat (limited to 'gcc/ada/gcc-interface/decl.c')
-rw-r--r-- | gcc/ada/gcc-interface/decl.c | 178 |
1 files changed, 97 insertions, 81 deletions
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 0a1f58a..4a8c4d0 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -179,6 +179,7 @@ static bool type_has_variable_size (tree); static tree elaborate_expression_1 (tree, Entity_Id, const char *, bool, bool); static tree elaborate_expression_2 (tree, Entity_Id, const char *, bool, bool, unsigned int); +static tree elaborate_reference (tree, Entity_Id, bool); static tree gnat_to_gnu_component_type (Entity_Id, bool, bool); static tree gnat_to_gnu_param (Entity_Id, Mechanism_Type, Entity_Id, bool, bool *); @@ -557,11 +558,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) break; } - /* If we have an external constant that we are not defining, get the - expression that is was defined to represent. We may throw it away - later if it is not a constant. But do not retrieve the expression - if it is an allocator because the designated type might be dummy - at this point. */ + /* If we have a constant that we are not defining, get the expression it + was defined to represent. This is necessary to avoid generating dumb + elaboration code in simple cases, but we may throw it away later if it + is not a constant. But do not retrieve it if it is an allocator since + the designated type might still be dummy at this point. */ if (!definition && !No_Initialization (Declaration_Node (gnat_entity)) && Present (Expression (Declaration_Node (gnat_entity))) @@ -995,32 +996,31 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) before the call to "=". */ if (TREE_CODE (inner) == TRUTH_ANDIF_EXPR) inner = TREE_OPERAND (inner, 1); - if (TREE_CODE (inner) == CALL_EXPR - || TREE_CODE (inner) == NULL_EXPR - || TREE_CODE (inner) == CONSTRUCTOR + if ((TREE_CODE (inner) == CALL_EXPR + && !call_is_atomic_load (inner)) + || TREE_CODE (inner) == NULL_EXPR + || TREE_CODE (inner) == CONSTRUCTOR || CONSTANT_CLASS_P (inner)) ; /* Case 2: if the renaming entity need not be materialized, use - the stabilized renamed expression for the renaming. At the - global level, we can do this only if we know no SAVE_EXPRs - need be made, because otherwise the expression would be tied - to a specific elaboration routine. */ - else if (!Materialize_Entity (gnat_entity) - && (!global_bindings_p () - || (staticp (gnu_expr) - && !TREE_SIDE_EFFECTS (gnu_expr)))) + the elaborated renamed expression for the renaming. But this + means that the caller is responsible for evaluating the address + of the renaming at the correct spot in the definition case to + instantiate the SAVE_EXPRs. */ + else if (!Materialize_Entity (gnat_entity)) { - gnu_decl = gnat_stabilize_reference (gnu_expr, true); + gnu_decl + = elaborate_reference (gnu_expr, gnat_entity, definition); - /* ??? No DECL_EXPR is created so we need to mark - the expression manually lest it is shared. */ + /* No DECL_EXPR will be created so the expression needs to be + marked manually because it will likely be shared. */ if (global_bindings_p ()) MARK_VISITED (gnu_decl); - /* This assertion will fail if the renamed object isn't - aligned enough as to make it possible to honor the - alignment set on the renaming. */ + /* This assertion will fail if the renamed object isn't aligned + enough as to make it possible to honor the alignment set on + the renaming. */ if (align) { unsigned int ralign = DECL_P (gnu_decl) @@ -1036,52 +1036,41 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) } /* Case 3: otherwise, make a constant pointer to the object we - are to rename and attach the object to the pointer after it - is stabilized. - - From the proper scope, attached objects will be referenced - directly instead of indirectly via the pointer to avoid - subtle aliasing problems with non-addressable entities. - They have to be stable because we must not evaluate the - variables in the expression every time the renaming is used. - The pointer is called a "renaming" pointer in this case. - - Note that we need to preserve the volatility of the renamed - object through the indirection. */ + are renaming and attach the object to the pointer after it is + elaborated. The object will be referenced directly instead + of indirectly via the pointer to avoid aliasing problems with + non-addressable entities. The pointer is called a "renaming" + pointer in this case. Note that we also need to preserve the + volatility of the renamed object through the indirection. */ else { if (TREE_THIS_VOLATILE (gnu_expr) && !TYPE_VOLATILE (gnu_type)) gnu_type = change_qualified_type (gnu_type, TYPE_QUAL_VOLATILE); + gnu_type = build_reference_type (gnu_type); - inner_const_flag = TREE_READONLY (gnu_expr); + used_by_ref = true; const_flag = true; + inner_const_flag = TREE_READONLY (gnu_expr); + gnu_size = NULL_TREE; - /* Stabilize and attach the expression to the pointer. - - Note that this might introduce SAVE_EXPRs and we don't - check whether we are 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. + renamed_obj + = elaborate_reference (gnu_expr, gnat_entity, definition); - These SAVE_EXPRs will be evaluated at the right place - by either the evaluation of the initializer for the - non-global case or the elaboration code for the global - case, and will be attached to the elaboration procedure - in the latter case. */ - renamed_obj = gnat_stabilize_reference (gnu_expr, true); + /* If we are not defining the entity, the expression will not + be attached through DECL_INITIAL so it needs to be marked + manually because it will likely be shared. Likewise for a + dereference as it will be folded by the ADDR_EXPR below. */ + if ((!definition || TREE_CODE (renamed_obj) == INDIRECT_REF) + && global_bindings_p ()) + MARK_VISITED (renamed_obj); if (type_annotate_only - && TREE_CODE (renamed_obj) == ERROR_MARK) + && TREE_CODE (renamed_obj) == ERROR_MARK) gnu_expr = NULL_TREE; else gnu_expr = build_unary_op (ADDR_EXPR, gnu_type, renamed_obj); - - gnu_size = NULL_TREE; - used_by_ref = true; } } @@ -1173,9 +1162,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) save_gnu_tree (gnat_entity, NULL_TREE, false); - /* Ignore the size. It's either meaningless or was handled - above. */ - gnu_size = NULL_TREE; /* Convert the type of the object to a reference type that can alias everything as per 13.3(19). */ gnu_type @@ -1185,6 +1171,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) const_flag = !Is_Public (gnat_entity) || compile_time_known_address_p (gnat_expr); + gnu_size = NULL_TREE; /* If this is a deferred constant, the initializer is attached to the full view. */ @@ -1221,6 +1208,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) alias everything as per 13.3(19). */ gnu_type = build_reference_type_for_mode (gnu_type, ptr_mode, true); + used_by_ref = true; gnu_size = NULL_TREE; /* No point in taking the address of an initializing expression @@ -1241,8 +1229,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) const_flag = true; } } - - used_by_ref = true; } /* If we are at top level and this object is of variable size, @@ -1269,8 +1255,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) || static_p))) { gnu_type = build_reference_type (gnu_type); - gnu_size = NULL_TREE; used_by_ref = true; + const_flag = true; + gnu_size = NULL_TREE; /* In case this was a aliased object whose nominal subtype is unconstrained, the pointer above will be a thin pointer and @@ -1313,13 +1300,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) gnu_expr = build_allocator (gnu_alloc_type, gnu_expr, gnu_type, Empty, Empty, gnat_entity, mutable_p); - const_flag = true; } else - { - gnu_expr = NULL_TREE; - const_flag = false; - } + gnu_expr = NULL_TREE; } /* If this object would go into the stack and has an alignment larger @@ -1357,9 +1340,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) build_component_ref (gnu_new_var, NULL_TREE, TYPE_FIELDS (gnu_new_type), false)); - gnu_size = NULL_TREE; used_by_ref = true; const_flag = true; + gnu_size = NULL_TREE; } /* If this is an aliased object with an unconstrained nominal subtype, @@ -1389,10 +1372,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_unc_var); TREE_CONSTANT (gnu_expr) = 1; - gnu_size = NULL_TREE; used_by_ref = true; - inner_const_flag = TREE_READONLY (gnu_unc_var); const_flag = true; + inner_const_flag = TREE_READONLY (gnu_unc_var); + gnu_size = NULL_TREE; } gnu_type @@ -1481,20 +1464,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) else if (kind == E_Loop_Parameter) DECL_LOOP_PARM_P (gnu_decl) = 1; - /* If this is a renaming pointer, attach the renamed object to it and - register it if we are at the global level and the renamed object - is a non-constant reference. */ + /* If this is a renaming pointer, attach the renamed object to it. */ if (renamed_obj) - { - SET_DECL_RENAMED_OBJECT (gnu_decl, renamed_obj); - - if (global_bindings_p () - && !gnat_constant_reference_p (renamed_obj)) - { - DECL_GLOBAL_NONCONSTANT_RENAMING_P (gnu_decl) = 1; - record_global_nonconstant_renaming (gnu_decl); - } - } + SET_DECL_RENAMED_OBJECT (gnu_decl, renamed_obj); /* If this is a constant and we are defining it or it generates a real symbol at the object level and we are referencing it, we may want @@ -6109,7 +6081,7 @@ prepend_attributes (struct attrib **attr_list, Entity_Id gnat_entity) /* Given a GNAT tree GNAT_EXPR, for an expression which is a value within a type definition (either a bound or a discriminant value) for GNAT_ENTITY, return the GCC tree to use for that expression. S is the suffix to use - if a variable needs to be created and DEFINITION is true if this is made + if a variable needs to be created and DEFINITION is true if this is done for a definition of GNAT_ENTITY. If NEED_VALUE is true, we need a result; otherwise, we are just elaborating the expression for side-effects. If NEED_DEBUG is true, we need a variable for debugging purposes even if it @@ -6250,6 +6222,50 @@ elaborate_expression_2 (tree gnu_expr, Entity_Id gnat_entity, const char *s, need_debug), unit_align); } + +/* Structure to hold internal data for elaborate_reference. */ + +struct er_data +{ + Entity_Id entity; + bool definition; +}; + +/* Wrapper function around elaborate_expression_1 for elaborate_reference. */ + +static tree +elaborate_reference_1 (tree ref, void *data, int n) +{ + struct er_data *er = (struct er_data *)data; + char suffix[16]; + + /* This is what elaborate_expression_1 does if NEED_DEBUG is false. */ + if (TREE_CONSTANT (ref)) + return ref; + + /* If this is a COMPONENT_REF of a fat pointer, elaborate the entire fat + pointer. This may be more efficient, but will also allow us to more + easily find the match for the PLACEHOLDER_EXPR. */ + if (TREE_CODE (ref) == COMPONENT_REF + && TYPE_IS_FAT_POINTER_P (TREE_TYPE (TREE_OPERAND (ref, 0)))) + return build3 (COMPONENT_REF, TREE_TYPE (ref), + elaborate_reference_1 (TREE_OPERAND (ref, 0), data, n), + TREE_OPERAND (ref, 1), TREE_OPERAND (ref, 2)); + + sprintf (suffix, "EXP%d", n); + return + elaborate_expression_1 (ref, er->entity, suffix, er->definition, false); +} + +/* Elaborate the reference REF to be used as renamed object for GNAT_ENTITY. + DEFINITION is true if this is done for a definition of GNAT_ENTITY. */ + +static tree +elaborate_reference (tree ref, Entity_Id gnat_entity, bool definition) +{ + struct er_data er = { gnat_entity, definition }; + return gnat_rewrite_reference (ref, elaborate_reference_1, &er); +} /* Given a GNU tree and a GNAT list of choices, generate an expression to test the value passed against the list of choices. */ |