diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-04-16 15:14:01 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-04-16 15:14:01 +0000 |
commit | dd329d30040f8c9e493bf85514c364d5ac5d6551 (patch) | |
tree | 009b43e2a42820164aa4dc34cf57b12d25d56b3a /gcc/ada/gcc-interface/trans.c | |
parent | 2eb0fcbc8f9d73d8061a4634e4e3c9169fc862d8 (diff) | |
download | gcc-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.c | 503 |
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; } |