aboutsummaryrefslogtreecommitdiff
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.c135
1 files changed, 70 insertions, 65 deletions
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index bf9ac15..7031bfb 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -2455,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.
@@ -2513,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;
@@ -2537,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)))