summaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/trans.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/gcc-interface/trans.c')
-rw-r--r--gcc/ada/gcc-interface/trans.c193
1 files changed, 105 insertions, 88 deletions
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index b4031896984..7031bfb447c 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -593,12 +593,14 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
others_decl
= create_var_decl (get_identifier ("OTHERS"),
get_identifier ("__gnat_others_value"),
- integer_type_node, 0, 1, 0, 1, 1, 0, Empty);
+ integer_type_node, NULL_TREE, true, false, true, false,
+ NULL, Empty);
all_others_decl
= create_var_decl (get_identifier ("ALL_OTHERS"),
get_identifier ("__gnat_all_others_value"),
- integer_type_node, 0, 1, 0, 1, 1, 0, Empty);
+ integer_type_node, NULL_TREE, true, false, true, false,
+ NULL, Empty);
main_identifier_node = get_identifier ("main");
@@ -2453,40 +2455,48 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
begin_subprog_body (gnu_subprog_decl);
- /* If there are Out parameters, we need to ensure that the return statement
- properly copies them out. We do this by making a new block and converting
- any inner return into a goto to a label at the end of the block. */
+ /* If there are In Out or Out parameters, we need to ensure that the return
+ statement properly copies them out. We do this by making a new block and
+ converting any return into a goto to a label at the end of the block. */
gnu_cico_list = TYPE_CI_CO_LIST (gnu_subprog_type);
- VEC_safe_push (tree, gc, gnu_return_label_stack,
- gnu_cico_list
- ? create_artificial_label (input_location)
- : NULL_TREE);
+ if (gnu_cico_list)
+ {
+ VEC_safe_push (tree, gc, gnu_return_label_stack,
+ create_artificial_label (input_location));
+
+ start_stmt_group ();
+ gnat_pushlevel ();
+
+ /* See whether there are parameters for which we don't have a GCC tree
+ yet. These must be Out parameters. Make a VAR_DECL for them and
+ put it into TYPE_CI_CO_LIST, which must contain an empty entry too.
+ We can match up the entries because TYPE_CI_CO_LIST is in the order
+ of the parameters. */
+ for (gnat_param = First_Formal_With_Extras (gnat_subprog_id);
+ Present (gnat_param);
+ gnat_param = Next_Formal_With_Extras (gnat_param))
+ if (!present_gnu_tree (gnat_param))
+ {
+ tree gnu_cico_entry = gnu_cico_list;
+
+ /* Skip any entries that have been already filled in; they must
+ correspond to In Out parameters. */
+ while (gnu_cico_entry && TREE_VALUE (gnu_cico_entry))
+ gnu_cico_entry = TREE_CHAIN (gnu_cico_entry);
+
+ /* Do any needed references for padded types. */
+ TREE_VALUE (gnu_cico_entry)
+ = convert (TREE_TYPE (TREE_PURPOSE (gnu_cico_entry)),
+ gnat_to_gnu_entity (gnat_param, NULL_TREE, 1));
+ }
+ }
+ else
+ VEC_safe_push (tree, gc, gnu_return_label_stack, NULL_TREE);
/* Get a tree corresponding to the code for the subprogram. */
start_stmt_group ();
gnat_pushlevel ();
- /* See if there are any parameters for which we don't yet have GCC entities.
- These must be for Out parameters for which we will be making VAR_DECL
- nodes here. Fill them in to TYPE_CI_CO_LIST, which must contain the empty
- entry as well. We can match up the entries because TYPE_CI_CO_LIST is in
- the order of the parameters. */
- for (gnat_param = First_Formal_With_Extras (gnat_subprog_id);
- Present (gnat_param);
- gnat_param = Next_Formal_With_Extras (gnat_param))
- if (!present_gnu_tree (gnat_param))
- {
- /* Skip any entries that have been already filled in; they must
- correspond to In Out parameters. */
- while (gnu_cico_list && TREE_VALUE (gnu_cico_list))
- gnu_cico_list = TREE_CHAIN (gnu_cico_list);
-
- /* Do any needed references for padded types. */
- TREE_VALUE (gnu_cico_list)
- = convert (TREE_TYPE (TREE_PURPOSE (gnu_cico_list)),
- gnat_to_gnu_entity (gnat_param, NULL_TREE, 1));
- }
-
/* On VMS, establish our condition handler to possibly turn a condition into
the corresponding exception if the subprogram has a foreign convention or
is exported.
@@ -2511,6 +2521,40 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
gnat_poplevel ();
gnu_result = end_stmt_group ();
+ /* If we are dealing with a return from an Ada procedure with parameters
+ passed by copy-in/copy-out, we need to return a record containing the
+ final values of these parameters. If the list contains only one entry,
+ return just that entry though.
+
+ For a full description of the copy-in/copy-out parameter mechanism, see
+ the part of the gnat_to_gnu_entity routine dealing with the translation
+ of subprograms.
+
+ We need to make a block that contains the definition of that label and
+ the copying of the return value. It first contains the function, then
+ the label and copy statement. */
+ if (gnu_cico_list)
+ {
+ tree gnu_retval;
+
+ add_stmt (gnu_result);
+ add_stmt (build1 (LABEL_EXPR, void_type_node,
+ VEC_last (tree, gnu_return_label_stack)));
+
+ if (list_length (gnu_cico_list) == 1)
+ gnu_retval = TREE_VALUE (gnu_cico_list);
+ else
+ gnu_retval = build_constructor_from_list (TREE_TYPE (gnu_subprog_type),
+ gnu_cico_list);
+
+ add_stmt_with_node (build_return_expr (gnu_result_decl, gnu_retval),
+ End_Label (Handled_Statement_Sequence (gnat_node)));
+ gnat_poplevel ();
+ gnu_result = end_stmt_group ();
+ }
+
+ VEC_pop (tree, gnu_return_label_stack);
+
/* If we populated the parameter attributes cache, we need to make sure
that the cached expressions are evaluated on all possible paths. */
cache = DECL_STRUCT_FUNCTION (gnu_subprog_decl)->language->parm_attr_cache;
@@ -2535,43 +2579,6 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
gnu_result = end_stmt_group ();
}
- /* If we are dealing with a return from an Ada procedure with parameters
- passed by copy-in/copy-out, we need to return a record containing the
- final values of these parameters. If the list contains only one entry,
- return just that entry though.
-
- For a full description of the copy-in/copy-out parameter mechanism, see
- the part of the gnat_to_gnu_entity routine dealing with the translation
- of subprograms.
-
- We need to make a block that contains the definition of that label and
- the copying of the return value. It first contains the function, then
- the label and copy statement. */
- if (VEC_last (tree, gnu_return_label_stack))
- {
- tree gnu_retval;
-
- start_stmt_group ();
- gnat_pushlevel ();
- add_stmt (gnu_result);
- add_stmt (build1 (LABEL_EXPR, void_type_node,
- VEC_last (tree, gnu_return_label_stack)));
-
- gnu_cico_list = TYPE_CI_CO_LIST (gnu_subprog_type);
- if (list_length (gnu_cico_list) == 1)
- gnu_retval = TREE_VALUE (gnu_cico_list);
- else
- gnu_retval = build_constructor_from_list (TREE_TYPE (gnu_subprog_type),
- gnu_cico_list);
-
- add_stmt_with_node (build_return_expr (gnu_result_decl, gnu_retval),
- End_Label (Handled_Statement_Sequence (gnat_node)));
- gnat_poplevel ();
- gnu_result = end_stmt_group ();
- }
-
- VEC_pop (tree, gnu_return_label_stack);
-
/* Set the end location. */
Sloc_to_locus
((Present (End_Label (Handled_Statement_Sequence (gnat_node)))
@@ -2673,7 +2680,7 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
so we can give them the scope of the elaboration routine at top level. */
else if (!current_function_decl)
{
- current_function_decl = VEC_last (tree, gnu_elab_proc_stack);
+ current_function_decl = get_elaboration_procedure ();
went_into_elab_proc = true;
}
@@ -2788,8 +2795,8 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
/* Create an explicit temporary holding the copy. This ensures that
its lifetime is as narrow as possible around a statement. */
gnu_temp = create_var_decl (create_tmp_var_name ("A"), NULL_TREE,
- TREE_TYPE (gnu_name), NULL_TREE, false,
- false, false, false, NULL, Empty);
+ TREE_TYPE (gnu_name), NULL_TREE,
+ false, false, false, false, NULL, Empty);
DECL_ARTIFICIAL (gnu_temp) = 1;
DECL_IGNORED_P (gnu_temp) = 1;
@@ -3210,8 +3217,8 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
gnu_jmpsave_decl = create_var_decl (get_identifier ("JMPBUF_SAVE"),
NULL_TREE, jmpbuf_ptr_type,
build_call_0_expr (get_jmpbuf_decl),
- false, false, false, false, NULL,
- gnat_node);
+ false, false, false, false,
+ NULL, gnat_node);
DECL_ARTIFICIAL (gnu_jmpsave_decl) = 1;
/* The __builtin_setjmp receivers will immediately reinstall it. Now
@@ -3220,8 +3227,8 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
it is uninitialized, although they will never be actually taken. */
TREE_NO_WARNING (gnu_jmpsave_decl) = 1;
gnu_jmpbuf_decl = create_var_decl (get_identifier ("JMP_BUF"),
- NULL_TREE, jmpbuf_type,
- NULL_TREE, false, false, false, false,
+ NULL_TREE, jmpbuf_type, NULL_TREE,
+ false, false, false, false,
NULL, gnat_node);
DECL_ARTIFICIAL (gnu_jmpbuf_decl) = 1;
@@ -3273,12 +3280,11 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
gnat_pushlevel ();
VEC_safe_push (tree, gc, gnu_except_ptr_stack,
- create_var_decl (get_identifier ("EXCEPT_PTR"),
- NULL_TREE,
+ create_var_decl (get_identifier ("EXCEPT_PTR"), NULL_TREE,
build_pointer_type (except_type_node),
build_call_0_expr (get_excptr_decl),
- false,
- false, false, false, NULL, gnat_node));
+ false, false, false, false,
+ NULL, gnat_node));
/* Generate code for each handler. The N_Exception_Handler case does the
real work and returns a COND_EXPR for each handler, which we chain
@@ -3537,8 +3543,8 @@ Exception_Handler_to_gnu_zcx (Node_Id gnat_node)
1, integer_zero_node);
gnu_incoming_exc_ptr = create_var_decl (get_identifier ("EXPTR"), NULL_TREE,
ptr_type_node, gnu_current_exc_ptr,
- false, false, false, false, NULL,
- gnat_node);
+ false, false, false, false,
+ NULL, gnat_node);
add_stmt_with_node (build_call_1_expr (begin_handler_decl,
gnu_incoming_exc_ptr),
@@ -3754,11 +3760,13 @@ gnat_to_gnu (Node_Id gnat_node)
|| kind == N_Handled_Sequence_Of_Statements
|| (IN (kind, N_Raise_xxx_Error) && Ekind (Etype (gnat_node)) == E_Void))
{
+ tree current_elab_proc = get_elaboration_procedure ();
+
/* If this is a statement and we are at top level, it must be part of
the elaboration procedure, so mark us as being in that procedure. */
if (!current_function_decl)
{
- current_function_decl = VEC_last (tree, gnu_elab_proc_stack);
+ current_function_decl = current_elab_proc;
went_into_elab_proc = true;
}
@@ -3769,7 +3777,7 @@ gnat_to_gnu (Node_Id gnat_node)
every nested real statement instead. This also avoids triggering
spurious errors on dummy (empty) sequences created by the front-end
for package bodies in some cases. */
- if (current_function_decl == VEC_last (tree, gnu_elab_proc_stack)
+ if (current_function_decl == current_elab_proc
&& kind != N_Handled_Sequence_Of_Statements)
Check_Elaboration_Code_Allowed (gnat_node);
}
@@ -3997,13 +4005,14 @@ gnat_to_gnu (Node_Id gnat_node)
is frozen. */
if (Present (Freeze_Node (gnat_temp)))
{
- if ((Is_Public (gnat_temp) || global_bindings_p ())
- && !TREE_CONSTANT (gnu_expr))
+ if (TREE_CONSTANT (gnu_expr))
+ ;
+ else if (global_bindings_p ())
gnu_expr
= create_var_decl (create_concat_name (gnat_temp, "init"),
- NULL_TREE, TREE_TYPE (gnu_expr),
- gnu_expr, false, Is_Public (gnat_temp),
- false, false, NULL, gnat_temp);
+ NULL_TREE, TREE_TYPE (gnu_expr), gnu_expr,
+ false, false, false, false,
+ NULL, gnat_temp);
else
gnu_expr = gnat_save_expr (gnu_expr);
@@ -5805,7 +5814,7 @@ add_decl_expr (tree gnu_decl, Entity_Id gnat_entity)
|| TREE_CODE (type) == QUAL_UNION_TYPE))
MARK_VISITED (TYPE_ADA_SIZE (type));
}
- else
+ else if (!DECL_EXTERNAL (gnu_decl))
add_stmt_with_node (gnu_stmt, gnat_entity);
/* If this is a variable and an initializer is attached to it, it must be
@@ -7661,4 +7670,12 @@ get_exception_label (char kind)
return NULL_TREE;
}
+/* Return the decl for the current elaboration procedure. */
+
+tree
+get_elaboration_procedure (void)
+{
+ return VEC_last (tree, gnu_elab_proc_stack);
+}
+
#include "gt-ada-trans.h"