summaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/trans.c
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-16 15:14:01 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-16 15:14:01 +0000
commitdd329d30040f8c9e493bf85514c364d5ac5d6551 (patch)
tree009b43e2a42820164aa4dc34cf57b12d25d56b3a /gcc/ada/gcc-interface/trans.c
parent2eb0fcbc8f9d73d8061a4634e4e3c9169fc862d8 (diff)
downloadgcc-dd329d30040f8c9e493bf85514c364d5ac5d6551.tar.gz
2016-04-16 Basile Starynkevitch <basile@starynkevitch.net>
{{merging with even more of GCC 6, using subversion 1.9 svn merge -r230196:230700 ^/trunk }} git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@235061 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/gcc-interface/trans.c')
-rw-r--r--gcc/ada/gcc-interface/trans.c503
1 files changed, 335 insertions, 168 deletions
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index a347b3b1a42..5ee82ec6f92 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -33,6 +33,7 @@
#include "gimple-expr.h"
#include "stringpool.h"
#include "cgraph.h"
+#include "predict.h"
#include "diagnostic.h"
#include "alias.h"
#include "fold-const.h"
@@ -181,6 +182,7 @@ struct GTY(()) range_check_info_d {
tree high_bound;
tree type;
tree invariant_cond;
+ tree inserted_cond;
};
typedef struct range_check_info_d *range_check_info;
@@ -423,6 +425,8 @@ gigi (Node_Id gnat_root,
= get_identifier ("system__standard_library__exception_data");
/* Make the types and functions used for exception processing. */
+ except_type_node = gnat_to_gnu_type (Base_Type (standard_exception_type));
+
jmpbuf_type
= build_array_type (gnat_type_for_mode (Pmode, 0),
build_index_type (size_int (5)));
@@ -443,6 +447,22 @@ gigi (Node_Id gnat_root,
NULL_TREE),
NULL_TREE, is_disabled, true, true, true, false, NULL, Empty);
+ get_excptr_decl
+ = create_subprog_decl
+ (get_identifier ("system__soft_links__get_gnat_exception"), NULL_TREE,
+ build_function_type_list (build_pointer_type (except_type_node),
+ NULL_TREE),
+ NULL_TREE, is_disabled, true, true, true, false, NULL, Empty);
+
+ not_handled_by_others_decl = get_identifier ("not_handled_by_others");
+ for (t = TYPE_FIELDS (except_type_node); t; t = DECL_CHAIN (t))
+ if (DECL_NAME (t) == not_handled_by_others_decl)
+ {
+ not_handled_by_others_decl = t;
+ break;
+ }
+ gcc_assert (DECL_P (not_handled_by_others_decl));
+
/* setjmp returns an integer and has one operand, which is a pointer to
a jmpbuf. */
setjmp_decl
@@ -464,6 +484,39 @@ gigi (Node_Id gnat_root,
DECL_BUILT_IN_CLASS (update_setjmp_buf_decl) = BUILT_IN_NORMAL;
DECL_FUNCTION_CODE (update_setjmp_buf_decl) = BUILT_IN_UPDATE_SETJMP_BUF;
+ raise_nodefer_decl
+ = create_subprog_decl
+ (get_identifier ("__gnat_raise_nodefer_with_msg"), NULL_TREE,
+ build_function_type_list (void_type_node,
+ build_pointer_type (except_type_node),
+ NULL_TREE),
+ NULL_TREE, is_disabled, true, true, true, false, NULL, Empty);
+
+ /* Indicate that it never returns. */
+ TREE_THIS_VOLATILE (raise_nodefer_decl) = 1;
+ TREE_SIDE_EFFECTS (raise_nodefer_decl) = 1;
+ TREE_TYPE (raise_nodefer_decl)
+ = build_qualified_type (TREE_TYPE (raise_nodefer_decl),
+ TYPE_QUAL_VOLATILE);
+
+ reraise_zcx_decl
+ = create_subprog_decl (get_identifier ("__gnat_reraise_zcx"), NULL_TREE,
+ ftype, NULL_TREE,
+ is_disabled, true, true, true, false,
+ NULL, Empty);
+ /* Indicate that these never return. */
+ TREE_THIS_VOLATILE (reraise_zcx_decl) = 1;
+ TREE_SIDE_EFFECTS (reraise_zcx_decl) = 1;
+ TREE_TYPE (reraise_zcx_decl)
+ = build_qualified_type (TREE_TYPE (reraise_zcx_decl), TYPE_QUAL_VOLATILE);
+
+ set_exception_parameter_decl
+ = create_subprog_decl
+ (get_identifier ("__gnat_set_exception_parameter"), NULL_TREE,
+ build_function_type_list (void_type_node, ptr_type_node, ptr_type_node,
+ NULL_TREE),
+ NULL_TREE, is_disabled, true, true, true, false, NULL, Empty);
+
/* Hooks to call when entering/leaving an exception handler. */
ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
@@ -485,16 +538,29 @@ gigi (Node_Id gnat_root,
is_disabled, true, true, true, false,
NULL, Empty);
- reraise_zcx_decl
- = create_subprog_decl (get_identifier ("__gnat_reraise_zcx"), NULL_TREE,
- ftype, NULL_TREE,
- is_disabled, true, true, true, false,
- NULL, Empty);
- /* Indicate that these never return. */
- TREE_THIS_VOLATILE (reraise_zcx_decl) = 1;
- TREE_SIDE_EFFECTS (reraise_zcx_decl) = 1;
- TREE_TYPE (reraise_zcx_decl)
- = build_qualified_type (TREE_TYPE (reraise_zcx_decl), TYPE_QUAL_VOLATILE);
+ /* Dummy objects to materialize "others" and "all others" in the exception
+ tables. These are exported by a-exexpr-gcc.adb, so see this unit for
+ the types to use. */
+ others_decl
+ = create_var_decl (get_identifier ("OTHERS"),
+ get_identifier ("__gnat_others_value"),
+ unsigned_char_type_node, NULL_TREE,
+ true, false, true, false, true, false,
+ NULL, Empty);
+
+ all_others_decl
+ = create_var_decl (get_identifier ("ALL_OTHERS"),
+ get_identifier ("__gnat_all_others_value"),
+ unsigned_char_type_node, NULL_TREE,
+ true, false, true, false, true, false,
+ NULL, Empty);
+
+ unhandled_others_decl
+ = create_var_decl (get_identifier ("UNHANDLED_OTHERS"),
+ get_identifier ("__gnat_unhandled_others_value"),
+ unsigned_char_type_node, NULL_TREE,
+ true, false, true, false, true, false,
+ NULL, Empty);
/* If in no exception handlers mode, all raise statements are redirected to
__gnat_last_chance_handler. No need to redefine raise_nodefer_decl since
@@ -530,39 +596,6 @@ gigi (Node_Id gnat_root,
? exception_range : exception_column);
}
- /* Set the types that GCC and Gigi use from the front end. */
- except_type_node = gnat_to_gnu_type (Base_Type (standard_exception_type));
-
- /* Make other functions used for exception processing. */
- get_excptr_decl
- = create_subprog_decl
- (get_identifier ("system__soft_links__get_gnat_exception"), NULL_TREE,
- build_function_type_list (build_pointer_type (except_type_node),
- NULL_TREE),
- NULL_TREE, is_disabled, true, true, true, false, NULL, Empty);
-
- set_exception_parameter_decl
- = create_subprog_decl
- (get_identifier ("__gnat_set_exception_parameter"), NULL_TREE,
- build_function_type_list (void_type_node, ptr_type_node, ptr_type_node,
- NULL_TREE),
- NULL_TREE, is_disabled, true, true, true, false, NULL, Empty);
-
- raise_nodefer_decl
- = create_subprog_decl
- (get_identifier ("__gnat_raise_nodefer_with_msg"), NULL_TREE,
- build_function_type_list (void_type_node,
- build_pointer_type (except_type_node),
- NULL_TREE),
- NULL_TREE, is_disabled, true, true, true, false, NULL, Empty);
-
- /* Indicate that it never returns. */
- TREE_THIS_VOLATILE (raise_nodefer_decl) = 1;
- TREE_SIDE_EFFECTS (raise_nodefer_decl) = 1;
- TREE_TYPE (raise_nodefer_decl)
- = build_qualified_type (TREE_TYPE (raise_nodefer_decl),
- TYPE_QUAL_VOLATILE);
-
/* Build the special descriptor type and its null node if needed. */
if (TARGET_VTABLE_USES_DESCRIPTORS)
{
@@ -596,30 +629,6 @@ gigi (Node_Id gnat_root,
longest_float_type_node
= get_unpadded_type (Base_Type (standard_long_long_float));
- /* Dummy objects to materialize "others" and "all others" in the exception
- tables. These are exported by a-exexpr-gcc.adb, so see this unit for
- the types to use. */
- others_decl
- = create_var_decl (get_identifier ("OTHERS"),
- get_identifier ("__gnat_others_value"),
- unsigned_char_type_node, NULL_TREE,
- true, false, true, false, true, false,
- NULL, Empty);
-
- all_others_decl
- = create_var_decl (get_identifier ("ALL_OTHERS"),
- get_identifier ("__gnat_all_others_value"),
- unsigned_char_type_node, NULL_TREE,
- true, false, true, false, true, false,
- NULL, Empty);
-
- unhandled_others_decl
- = create_var_decl (get_identifier ("UNHANDLED_OTHERS"),
- get_identifier ("__gnat_unhandled_others_value"),
- unsigned_char_type_node, NULL_TREE,
- true, false, true, false, true, false,
- NULL, Empty);
-
main_identifier_node = get_identifier ("main");
/* Install the builtins we might need, either internally or as
@@ -975,6 +984,9 @@ fold_constant_decl_in_expr (tree exp)
case ARRAY_REF:
case ARRAY_RANGE_REF:
+ /* If the index is not itself constant, then nothing can be folded. */
+ if (!TREE_CONSTANT (TREE_OPERAND (exp, 1)))
+ return exp;
op0 = fold_constant_decl_in_expr (TREE_OPERAND (exp, 0));
if (op0 == TREE_OPERAND (exp, 0))
return exp;
@@ -1027,7 +1039,8 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
original type. Similarly, a class-wide type is equivalent to a subtype of
itself. Finally, if the types are Itypes, one may be a copy of the other,
which is also legal. */
- gnat_temp = (Nkind (gnat_node) == N_Defining_Identifier
+ gnat_temp = ((Nkind (gnat_node) == N_Defining_Identifier
+ || Nkind (gnat_node) == N_Defining_Operator_Symbol)
? gnat_node : Entity (gnat_node));
gnat_temp_type = Etype (gnat_temp);
@@ -2446,8 +2459,8 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
gnu_result
= build_compound_expr (gnu_result_type, asm_expr,
- build_component_ref (rec_val, NULL_TREE,
- field, false));
+ build_component_ref (rec_val, field,
+ false));
}
break;
@@ -2714,6 +2727,24 @@ can_be_lower_p (tree val1, tree val2)
return tree_int_cst_lt (val1, val2);
}
+/* Replace EXPR1 and EXPR2 by invariant expressions if possible. Return
+ true if both expressions have been replaced and false otherwise. */
+
+static bool
+make_invariant (tree *expr1, tree *expr2)
+{
+ tree inv_expr1 = gnat_invariant_expr (*expr1);
+ tree inv_expr2 = gnat_invariant_expr (*expr2);
+
+ if (inv_expr1)
+ *expr1 = inv_expr1;
+
+ if (inv_expr2)
+ *expr2 = inv_expr2;
+
+ return inv_expr1 && inv_expr2;
+}
+
/* Helper function for walk_tree, used by independent_iterations_p below. */
static tree
@@ -3078,48 +3109,60 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
the LOOP_STMT to it, finish it and make it the "loop". */
if (Present (gnat_iter_scheme) && No (Condition (gnat_iter_scheme)))
{
- struct range_check_info_d *rci;
- unsigned n_checks = vec_safe_length (gnu_loop_info->checks);
- unsigned int i;
-
- /* First, if we have computed a small number of invariant conditions for
- range checks applied to the iteration variable, then initialize these
- conditions in front of the loop. Otherwise, leave them set to true.
-
- ??? The heuristics need to be improved, by taking into account the
- following datapoints:
- - loop unswitching is disabled for big loops. The cap is the
- parameter PARAM_MAX_UNSWITCH_INSNS (50).
- - loop unswitching can only be applied a small number of times
- to a given loop. The cap is PARAM_MAX_UNSWITCH_LEVEL (3).
- - the front-end quickly generates useless or redundant checks
- that can be entirely optimized away in the end. */
- if (1 <= n_checks && n_checks <= 4)
- FOR_EACH_VEC_ELT (*gnu_loop_info->checks, i, rci)
- {
- tree low_ok
- = rci->low_bound
- ? build_binary_op (GE_EXPR, boolean_type_node,
- convert (rci->type, gnu_low),
- rci->low_bound)
- : boolean_true_node;
-
- tree high_ok
- = rci->high_bound
- ? build_binary_op (LE_EXPR, boolean_type_node,
- convert (rci->type, gnu_high),
- rci->high_bound)
- : boolean_true_node;
-
- tree range_ok
- = build_binary_op (TRUTH_ANDIF_EXPR, boolean_type_node,
- low_ok, high_ok);
-
- TREE_OPERAND (rci->invariant_cond, 0)
- = build_unary_op (TRUTH_NOT_EXPR, boolean_type_node, range_ok);
-
- add_stmt_with_node_force (rci->invariant_cond, gnat_node);
- }
+ /* First, if we have computed invariant conditions for range (or index)
+ checks applied to the iteration variable, find out whether they can
+ be evaluated to false at compile time; otherwise, if there are not
+ too many of them, combine them with the original checks. If loop
+ unswitching is enabled, do not require the loop bounds to be also
+ invariant, as their evaluation will still be ahead of the loop. */
+ if (vec_safe_length (gnu_loop_info->checks) > 0
+ && (make_invariant (&gnu_low, &gnu_high) || flag_unswitch_loops))
+ {
+ struct range_check_info_d *rci;
+ unsigned int i, n_remaining_checks = 0;
+
+ FOR_EACH_VEC_ELT (*gnu_loop_info->checks, i, rci)
+ {
+ tree low_ok
+ = rci->low_bound
+ ? build_binary_op (GE_EXPR, boolean_type_node,
+ convert (rci->type, gnu_low),
+ rci->low_bound)
+ : boolean_true_node;
+
+ tree high_ok
+ = rci->high_bound
+ ? build_binary_op (LE_EXPR, boolean_type_node,
+ convert (rci->type, gnu_high),
+ rci->high_bound)
+ : boolean_true_node;
+
+ tree range_ok
+ = build_binary_op (TRUTH_ANDIF_EXPR, boolean_type_node,
+ low_ok, high_ok);
+
+ rci->invariant_cond
+ = build_unary_op (TRUTH_NOT_EXPR, boolean_type_node, range_ok);
+
+ if (rci->invariant_cond == boolean_false_node)
+ TREE_OPERAND (rci->inserted_cond, 0) = rci->invariant_cond;
+ else
+ n_remaining_checks++;
+ }
+
+ /* Note that loop unswitching can only be applied a small number of
+ times to a given loop (PARAM_MAX_UNSWITCH_LEVEL default to 3). */
+ if (0 < n_remaining_checks && n_remaining_checks <= 3
+ && optimize > 1 && !optimize_size)
+ FOR_EACH_VEC_ELT (*gnu_loop_info->checks, i, rci)
+ if (rci->invariant_cond != boolean_false_node)
+ {
+ TREE_OPERAND (rci->inserted_cond, 0) = rci->invariant_cond;
+
+ if (flag_unswitch_loops)
+ add_stmt_with_node_force (rci->inserted_cond, gnat_node);
+ }
+ }
/* Second, if loop vectorization is enabled and the iterations of the
loop can easily be proved as independent, mark the loop. */
@@ -3861,8 +3904,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
for (t = TREE_CHAIN (gnu_cico_list); t; t = TREE_CHAIN (t))
{
tree gnu_field_deref
- = build_component_ref (gnu_ret_deref, NULL_TREE,
- TREE_PURPOSE (t), true);
+ = build_component_ref (gnu_ret_deref, TREE_PURPOSE (t), true);
gnu_result = build2 (MODIFY_EXPR, void_type_node,
gnu_field_deref, TREE_VALUE (t));
add_stmt_with_node (gnu_result, gnat_end_label);
@@ -4694,8 +4736,8 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
tree gnu_result
= length == 1
? gnu_call
- : build_component_ref (gnu_call, NULL_TREE,
- TREE_PURPOSE (gnu_cico_list), false);
+ : build_component_ref (gnu_call, TREE_PURPOSE (gnu_cico_list),
+ false);
/* If the actual is a conversion, get the inner expression, which
will be the real destination, and convert the result to the
@@ -4782,8 +4824,8 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
if (TYPE_CI_CO_LIST (gnu_subprog_type))
{
tree gnu_elmt = TYPE_CI_CO_LIST (gnu_subprog_type);
- gnu_call = build_component_ref (gnu_call, NULL_TREE,
- TREE_PURPOSE (gnu_elmt), false);
+ gnu_call
+ = build_component_ref (gnu_call, TREE_PURPOSE (gnu_elmt), false);
gnu_result_type = TREE_TYPE (gnu_call);
}
@@ -5138,7 +5180,7 @@ Exception_Handler_to_gnu_sjlj (Node_Id gnat_node)
(build_unary_op
(INDIRECT_REF, NULL_TREE,
gnu_except_ptr_stack->last ()),
- get_identifier ("not_handled_by_others"), NULL_TREE,
+ not_handled_by_others_decl,
false)),
integer_zero_node);
}
@@ -5392,6 +5434,31 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
process_deferred_decl_context (true);
}
+/* Mark COND, a boolean expression, as predicating a call to a noreturn
+ function, i.e. predict that it is very likely false, and return it.
+
+ The compiler will automatically predict the last edge leading to a call
+ to a noreturn function as very unlikely taken. This function makes it
+ possible to expand the prediction to predecessors in case the condition
+ is made up of several short-circuit operators. */
+
+static tree
+build_noreturn_cond (tree cond)
+{
+ tree fn = builtin_decl_explicit (BUILT_IN_EXPECT);
+ tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ tree pred_type = TREE_VALUE (arg_types);
+ tree expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
+
+ tree t = build_call_expr (fn, 3,
+ fold_convert (pred_type, cond),
+ build_int_cst (expected_type, 0),
+ build_int_cst (integer_type_node,
+ PRED_NORETURN));
+
+ return build1 (NOP_EXPR, boolean_type_node, t);
+}
+
/* Subroutine of gnat_to_gnu to translate gnat_node, an N_Raise_xxx_Error,
to a GCC tree, which is returned. GNU_RESULT_TYPE_P is a pointer to where
we should place the result type. LABEL_P is true if there is a label to
@@ -5463,18 +5530,29 @@ Raise_Error_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
= build_call_raise_range (reason, gnat_node, gnu_index,
gnu_low_bound, gnu_high_bound);
- /* If loop unswitching is enabled, we try to compute invariant
- conditions for checks applied to iteration variables, i.e.
- conditions that are both independent of the variable and
- necessary in order for the check to fail in the course of
- some iteration, and prepend them to the original condition
- of the checks. This will make it possible later for the
- loop unswitching pass to replace the loop with two loops,
- one of which has the checks eliminated and the other has
- the original checks reinstated, and a run time selection.
- The former loop will be suitable for vectorization. */
+ /* If optimization is enabled and we are inside a loop, we try to
+ compute invariant conditions for checks applied to the iteration
+ variable, i.e. conditions that are independent of the variable
+ and necessary in order for the checks to fail in the course of
+ some iteration. If we succeed, we consider an alternative:
+
+ 1. If loop unswitching is enabled, we prepend these conditions
+ to the original conditions of the checks. This will make it
+ possible for the loop unswitching pass to replace the loop
+ with two loops, one of which has the checks eliminated and
+ the other has the original checks reinstated, and a prologue
+ implementing a run-time selection. The former loop will be
+ for example suitable for vectorization.
+
+ 2. Otherwise, we instead append the conditions to the original
+ conditions of the checks. At worse, if the conditions cannot
+ be evaluated at compile time, they will be evaluated as true
+ at run time only when the checks have already failed, thus
+ contributing negatively only to the size of the executable.
+ But the hope is that these invariant conditions be evaluated
+ at compile time to false, thus taking away the entire checks
+ with them. */
if (optimize
- && flag_unswitch_loops
&& inside_loop_p ()
&& (!gnu_low_bound
|| (gnu_low_bound = gnat_invariant_expr (gnu_low_bound)))
@@ -5486,14 +5564,21 @@ Raise_Error_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
rci->low_bound = gnu_low_bound;
rci->high_bound = gnu_high_bound;
rci->type = get_unpadded_type (gnat_type);
- rci->invariant_cond = build1 (SAVE_EXPR, boolean_type_node,
- boolean_true_node);
+ rci->inserted_cond
+ = build1 (SAVE_EXPR, boolean_type_node, boolean_true_node);
vec_safe_push (loop->checks, rci);
loop->has_checks = true;
- gnu_cond = build_binary_op (TRUTH_ANDIF_EXPR,
- boolean_type_node,
- rci->invariant_cond,
- gnat_to_gnu (gnat_cond));
+ gnu_cond = build_noreturn_cond (gnat_to_gnu (gnat_cond));
+ if (flag_unswitch_loops)
+ gnu_cond = build_binary_op (TRUTH_ANDIF_EXPR,
+ boolean_type_node,
+ rci->inserted_cond,
+ gnu_cond);
+ else
+ gnu_cond = build_binary_op (TRUTH_ANDIF_EXPR,
+ boolean_type_node,
+ gnu_cond,
+ rci->inserted_cond);
}
/* Or else, if aggressive loop optimizations are enabled, we just
@@ -5694,6 +5779,7 @@ gnat_to_gnu (Node_Id gnat_node)
case N_Expanded_Name:
case N_Operator_Symbol:
case N_Defining_Identifier:
+ case N_Defining_Operator_Symbol:
gnu_result = Identifier_to_gnu (gnat_node, &gnu_result_type);
/* If atomic access is required on the RHS, build the atomic load. */
@@ -5957,13 +6043,40 @@ gnat_to_gnu (Node_Id gnat_node)
}
break;
+ case N_Subprogram_Renaming_Declaration:
+ {
+ const Node_Id gnat_renaming = Defining_Entity (gnat_node);
+ const Node_Id gnat_renamed = Renamed_Entity (gnat_renaming);
+
+ gnu_result = alloc_stmt_list ();
+
+ /* Materializing renamed subprograms will only benefit the debugging
+ information as they aren't referenced in the generated code. So
+ skip them when they aren't needed. Avoid doing this if:
+
+ - there is a freeze node: in this case the renamed entity is not
+ elaborated yet,
+ - the renamed subprogram is intrinsic: it will not be available in
+ the debugging information (note that both or only one of the
+ renaming and the renamed subprograms can be intrinsic). */
+ if (!type_annotate_only
+ && Needs_Debug_Info (gnat_renaming)
+ && No (Freeze_Node (gnat_renaming))
+ && Present (gnat_renamed)
+ && (Ekind (gnat_renamed) == E_Function
+ || Ekind (gnat_renamed) == E_Procedure)
+ && !Is_Intrinsic_Subprogram (gnat_renaming)
+ && !Is_Intrinsic_Subprogram (gnat_renamed))
+ gnat_to_gnu_entity (gnat_renaming, gnat_to_gnu (gnat_renamed), 1);
+ break;
+ }
+
case N_Implicit_Label_Declaration:
gnat_to_gnu_entity (Defining_Entity (gnat_node), NULL_TREE, 1);
gnu_result = alloc_stmt_list ();
break;
case N_Number_Declaration:
- case N_Subprogram_Renaming_Declaration:
case N_Package_Renaming_Declaration:
/* These are fully handled in the front end. */
/* ??? For package renamings, find a way to use GENERIC namespaces so
@@ -6224,7 +6337,7 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_field = gnat_to_gnu_field_decl (gnat_field);
gnu_result
- = build_component_ref (gnu_prefix, NULL_TREE, gnu_field,
+ = build_component_ref (gnu_prefix, gnu_field,
(Nkind (Parent (gnat_node))
== N_Attribute_Reference)
&& lvalue_required_for_attribute_p
@@ -8240,7 +8353,69 @@ gnat_gimplify_stmt (tree *stmt_p)
}
}
-/* Force references to each of the entities in packages withed by GNAT_NODE.
+/* Force a reference to each of the entities in GNAT_PACKAGE recursively.
+
+ This routine is exclusively called in type_annotate mode, to compute DDA
+ information for types in withed units, for ASIS use. */
+
+static void
+elaborate_all_entities_for_package (Entity_Id gnat_package)
+{
+ Entity_Id gnat_entity;
+
+ for (gnat_entity = First_Entity (gnat_package);
+ Present (gnat_entity);
+ gnat_entity = Next_Entity (gnat_entity))
+ {
+ const Entity_Kind kind = Ekind (gnat_entity);
+
+ /* We are interested only in entities visible from the main unit. */
+ if (!Is_Public (gnat_entity))
+ continue;
+
+ /* Skip stuff internal to the compiler. */
+ if (Convention (gnat_entity) == Convention_Intrinsic)
+ continue;
+ if (kind == E_Operator)
+ continue;
+ if (IN (kind, Subprogram_Kind) && Is_Intrinsic_Subprogram (gnat_entity))
+ continue;
+
+ /* Skip named numbers. */
+ if (IN (kind, Named_Kind))
+ continue;
+
+ /* Skip generic declarations. */
+ if (IN (kind, Generic_Unit_Kind))
+ continue;
+
+ /* Skip package bodies. */
+ if (kind == E_Package_Body)
+ continue;
+
+ /* Skip limited views that point back to the main unit. */
+ if (IN (kind, Incomplete_Kind)
+ && From_Limited_With (gnat_entity)
+ && In_Extended_Main_Code_Unit (Non_Limited_View (gnat_entity)))
+ continue;
+
+ /* Skip types that aren't frozen. */
+ if (IN (kind, Type_Kind) && !Is_Frozen (gnat_entity))
+ continue;
+
+ /* Recurse on real packages that aren't in the main unit. */
+ if (kind == E_Package)
+ {
+ if (No (Renamed_Entity (gnat_entity))
+ && !In_Extended_Main_Code_Unit (gnat_entity))
+ elaborate_all_entities_for_package (gnat_entity);
+ }
+ else
+ gnat_to_gnu_entity (gnat_entity, NULL_TREE, 0);
+ }
+}
+
+/* Force a reference to each of the entities in packages withed by GNAT_NODE.
Operate recursively but check that we aren't elaborating something more
than once.
@@ -8250,7 +8425,7 @@ gnat_gimplify_stmt (tree *stmt_p)
static void
elaborate_all_entities (Node_Id gnat_node)
{
- Entity_Id gnat_with_clause, gnat_entity;
+ Entity_Id gnat_with_clause;
/* Process each unit only once. As we trace the context of all relevant
units transitively, including generic bodies, we may encounter the
@@ -8268,35 +8443,17 @@ elaborate_all_entities (Node_Id gnat_node)
&& !present_gnu_tree (Library_Unit (gnat_with_clause))
&& Library_Unit (gnat_with_clause) != Library_Unit (Cunit (Main_Unit)))
{
- elaborate_all_entities (Library_Unit (gnat_with_clause));
+ Node_Id gnat_unit = Library_Unit (gnat_with_clause);
+ Entity_Id gnat_entity = Entity (Name (gnat_with_clause));
- if (Ekind (Entity (Name (gnat_with_clause))) == E_Package)
- {
- for (gnat_entity = First_Entity (Entity (Name (gnat_with_clause)));
- Present (gnat_entity);
- gnat_entity = Next_Entity (gnat_entity))
- if (Is_Public (gnat_entity)
- && Convention (gnat_entity) != Convention_Intrinsic
- && Ekind (gnat_entity) != E_Package
- && Ekind (gnat_entity) != E_Package_Body
- && Ekind (gnat_entity) != E_Operator
- && !(IN (Ekind (gnat_entity), Type_Kind)
- && !Is_Frozen (gnat_entity))
- && !(IN (Ekind (gnat_entity), Incomplete_Kind)
- && From_Limited_With (gnat_entity)
- && In_Extended_Main_Code_Unit
- (Non_Limited_View (gnat_entity)))
- && !((Ekind (gnat_entity) == E_Procedure
- || Ekind (gnat_entity) == E_Function)
- && Is_Intrinsic_Subprogram (gnat_entity))
- && !IN (Ekind (gnat_entity), Named_Kind)
- && !IN (Ekind (gnat_entity), Generic_Unit_Kind))
- gnat_to_gnu_entity (gnat_entity, NULL_TREE, 0);
- }
- else if (Ekind (Entity (Name (gnat_with_clause))) == E_Generic_Package)
+ elaborate_all_entities (gnat_unit);
+
+ if (Ekind (gnat_entity) == E_Package)
+ elaborate_all_entities_for_package (gnat_entity);
+
+ else if (Ekind (gnat_entity) == E_Generic_Package)
{
- Node_Id gnat_body
- = Corresponding_Body (Unit (Library_Unit (gnat_with_clause)));
+ Node_Id gnat_body = Corresponding_Body (Unit (gnat_unit));
/* Retrieve compilation unit node of generic body. */
while (Present (gnat_body)
@@ -8553,6 +8710,12 @@ process_decls (List_Id gnat_decls, List_Id gnat_decls2,
|| Nkind (gnat_decl) == N_Protected_Body_Stub)
;
+ /* Renamed subprograms may not be elaborated yet at this point
+ since renamings do not trigger freezing. Wait for the second
+ pass to take care of them. */
+ else if (Nkind (gnat_decl) == N_Subprogram_Renaming_Declaration)
+ ;
+
else
add_stmt (gnat_to_gnu (gnat_decl));
}
@@ -8581,6 +8744,9 @@ process_decls (List_Id gnat_decls, List_Id gnat_decls2,
else if (Nkind (gnat_decl) == N_Freeze_Entity)
process_decls (Actions (gnat_decl), Empty, Empty, false, true);
+
+ else if (Nkind (gnat_decl) == N_Subprogram_Renaming_Declaration)
+ add_stmt (gnat_to_gnu (gnat_decl));
}
}
@@ -9612,7 +9778,8 @@ Sloc_to_locus (Source_Ptr Sloc, location_t *locus, bool clear_column)
line = 1;
/* Translate the location. */
- *locus = linemap_position_for_line_and_column (map, line, column);
+ *locus = linemap_position_for_line_and_column (line_table, map,
+ line, column);
return true;
}