Commit a963da4d by Eric Botcazou Committed by Eric Botcazou

trans.c (gnat_pushdecl): Do not do anything special for PARM_DECLs.

	* gcc-interface/trans.c (gnat_pushdecl): Do not do anything special
	for PARM_DECLs.
	(end_subprog_body): If the body is a BIND_EXPR, make its associated
	block the top-level one.
	(build_function_stub): Build a statement group for the whole function.
	* gcc-interface/utils.c (Subprogram_Body_to_gnu): If copy-in/copy-out
	is used, create the enclosing block early and process first the OUT
	parameters.

From-SVN: r164422
parent 0b182178
2010-09-19 Eric Botcazou <ebotcazou@adacore.com> 2010-09-19 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/trans.c (gnat_pushdecl): Do not do anything special
for PARM_DECLs.
(end_subprog_body): If the body is a BIND_EXPR, make its associated
block the top-level one.
(build_function_stub): Build a statement group for the whole function.
* gcc-interface/utils.c (Subprogram_Body_to_gnu): If copy-in/copy-out
is used, create the enclosing block early and process first the OUT
parameters.
2010-09-19 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Enumeration_Type>: Do * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Enumeration_Type>: Do
not generate debug info for individual enumerators. not generate debug info for individual enumerators.
......
...@@ -2455,39 +2455,47 @@ Subprogram_Body_to_gnu (Node_Id gnat_node) ...@@ -2455,39 +2455,47 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
begin_subprog_body (gnu_subprog_decl); begin_subprog_body (gnu_subprog_decl);
/* If there are Out parameters, we need to ensure that the return statement /* If there are In Out or Out parameters, we need to ensure that the return
properly copies them out. We do this by making a new block and converting statement properly copies them out. We do this by making a new block and
any inner return into a goto to a label at the end of the block. */ 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); gnu_cico_list = TYPE_CI_CO_LIST (gnu_subprog_type);
if (gnu_cico_list)
{
VEC_safe_push (tree, gc, gnu_return_label_stack, VEC_safe_push (tree, gc, gnu_return_label_stack,
gnu_cico_list create_artificial_label (input_location));
? create_artificial_label (input_location)
: NULL_TREE);
/* Get a tree corresponding to the code for the subprogram. */
start_stmt_group (); start_stmt_group ();
gnat_pushlevel (); gnat_pushlevel ();
/* See if there are any parameters for which we don't yet have GCC entities. /* See whether there are parameters for which we don't have a GCC tree
These must be for Out parameters for which we will be making VAR_DECL yet. These must be Out parameters. Make a VAR_DECL for them and
nodes here. Fill them in to TYPE_CI_CO_LIST, which must contain the empty put it into TYPE_CI_CO_LIST, which must contain an empty entry too.
entry as well. We can match up the entries because TYPE_CI_CO_LIST is in We can match up the entries because TYPE_CI_CO_LIST is in the order
the order of the parameters. */ of the parameters. */
for (gnat_param = First_Formal_With_Extras (gnat_subprog_id); for (gnat_param = First_Formal_With_Extras (gnat_subprog_id);
Present (gnat_param); Present (gnat_param);
gnat_param = Next_Formal_With_Extras (gnat_param)) gnat_param = Next_Formal_With_Extras (gnat_param))
if (!present_gnu_tree (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 /* Skip any entries that have been already filled in; they must
correspond to In Out parameters. */ correspond to In Out parameters. */
while (gnu_cico_list && TREE_VALUE (gnu_cico_list)) while (gnu_cico_entry && TREE_VALUE (gnu_cico_entry))
gnu_cico_list = TREE_CHAIN (gnu_cico_list); gnu_cico_entry = TREE_CHAIN (gnu_cico_entry);
/* Do any needed references for padded types. */ /* Do any needed references for padded types. */
TREE_VALUE (gnu_cico_list) TREE_VALUE (gnu_cico_entry)
= convert (TREE_TYPE (TREE_PURPOSE (gnu_cico_list)), = convert (TREE_TYPE (TREE_PURPOSE (gnu_cico_entry)),
gnat_to_gnu_entity (gnat_param, NULL_TREE, 1)); 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 ();
/* On VMS, establish our condition handler to possibly turn a condition into /* On VMS, establish our condition handler to possibly turn a condition into
the corresponding exception if the subprogram has a foreign convention or the corresponding exception if the subprogram has a foreign convention or
...@@ -2513,30 +2521,6 @@ Subprogram_Body_to_gnu (Node_Id gnat_node) ...@@ -2513,30 +2521,6 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
gnat_poplevel (); gnat_poplevel ();
gnu_result = end_stmt_group (); gnu_result = end_stmt_group ();
/* 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;
if (cache)
{
struct parm_attr_d *pa;
int i;
start_stmt_group ();
FOR_EACH_VEC_ELT (parm_attr, cache, i, pa)
{
if (pa->first)
add_stmt_with_node (pa->first, gnat_node);
if (pa->last)
add_stmt_with_node (pa->last, gnat_node);
if (pa->length)
add_stmt_with_node (pa->length, gnat_node);
}
add_stmt (gnu_result);
gnu_result = end_stmt_group ();
}
/* If we are dealing with a return from an Ada procedure with parameters /* 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 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, final values of these parameters. If the list contains only one entry,
...@@ -2549,17 +2533,14 @@ Subprogram_Body_to_gnu (Node_Id gnat_node) ...@@ -2549,17 +2533,14 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
We need to make a block that contains the definition of that label and 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 copying of the return value. It first contains the function, then
the label and copy statement. */ the label and copy statement. */
if (VEC_last (tree, gnu_return_label_stack)) if (gnu_cico_list)
{ {
tree gnu_retval; tree gnu_retval;
start_stmt_group ();
gnat_pushlevel ();
add_stmt (gnu_result); add_stmt (gnu_result);
add_stmt (build1 (LABEL_EXPR, void_type_node, add_stmt (build1 (LABEL_EXPR, void_type_node,
VEC_last (tree, gnu_return_label_stack))); VEC_last (tree, gnu_return_label_stack)));
gnu_cico_list = TYPE_CI_CO_LIST (gnu_subprog_type);
if (list_length (gnu_cico_list) == 1) if (list_length (gnu_cico_list) == 1)
gnu_retval = TREE_VALUE (gnu_cico_list); gnu_retval = TREE_VALUE (gnu_cico_list);
else else
...@@ -2574,6 +2555,30 @@ Subprogram_Body_to_gnu (Node_Id gnat_node) ...@@ -2574,6 +2555,30 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
VEC_pop (tree, gnu_return_label_stack); 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;
if (cache)
{
struct parm_attr_d *pa;
int i;
start_stmt_group ();
FOR_EACH_VEC_ELT (parm_attr, cache, i, pa)
{
if (pa->first)
add_stmt_with_node (pa->first, gnat_node);
if (pa->last)
add_stmt_with_node (pa->last, gnat_node);
if (pa->length)
add_stmt_with_node (pa->length, gnat_node);
}
add_stmt (gnu_result);
gnu_result = end_stmt_group ();
}
/* Set the end location. */ /* Set the end location. */
Sloc_to_locus Sloc_to_locus
((Present (End_Label (Handled_Statement_Sequence (gnat_node))) ((Present (End_Label (Handled_Statement_Sequence (gnat_node)))
......
...@@ -473,14 +473,8 @@ gnat_pushdecl (tree decl, Node_Id gnat_node) ...@@ -473,14 +473,8 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
} }
else if (!DECL_EXTERNAL (decl)) else if (!DECL_EXTERNAL (decl))
{ {
tree block; DECL_CHAIN (decl) = BLOCK_VARS (current_binding_level->block);
/* Fake PARM_DECLs go into the topmost block of the function. */ BLOCK_VARS (current_binding_level->block) = decl;
if (TREE_CODE (decl) == PARM_DECL)
block = BLOCK_SUPERCONTEXT (current_binding_level->block);
else
block = current_binding_level->block;
DECL_CHAIN (decl) = BLOCK_VARS (block);
BLOCK_VARS (block) = decl;
} }
} }
...@@ -1907,6 +1901,13 @@ end_subprog_body (tree body) ...@@ -1907,6 +1901,13 @@ end_subprog_body (tree body)
/* Mark the RESULT_DECL as being in this subprogram. */ /* Mark the RESULT_DECL as being in this subprogram. */
DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl; DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
/* The body should be a BIND_EXPR whose BLOCK is the top-level one. */
if (TREE_CODE (body) == BIND_EXPR)
{
BLOCK_SUPERCONTEXT (BIND_EXPR_BLOCK (body)) = fndecl;
DECL_INITIAL (fndecl) = BIND_EXPR_BLOCK (body);
}
DECL_SAVED_TREE (fndecl) = body; DECL_SAVED_TREE (fndecl) = body;
current_function_decl = DECL_CONTEXT (fndecl); current_function_decl = DECL_CONTEXT (fndecl);
...@@ -3228,15 +3229,18 @@ build_function_stub (tree gnu_subprog, Entity_Id gnat_subprog) ...@@ -3228,15 +3229,18 @@ build_function_stub (tree gnu_subprog, Entity_Id gnat_subprog)
tree gnu_subprog_type, gnu_subprog_addr, gnu_subprog_call; tree gnu_subprog_type, gnu_subprog_addr, gnu_subprog_call;
tree gnu_stub_param, gnu_arg_types, gnu_param; tree gnu_stub_param, gnu_arg_types, gnu_param;
tree gnu_stub_decl = DECL_FUNCTION_STUB (gnu_subprog); tree gnu_stub_decl = DECL_FUNCTION_STUB (gnu_subprog);
tree gnu_body;
VEC(tree,gc) *gnu_param_vec = NULL; VEC(tree,gc) *gnu_param_vec = NULL;
gnu_subprog_type = TREE_TYPE (gnu_subprog); gnu_subprog_type = TREE_TYPE (gnu_subprog);
/* Initialize the information structure for the function. */
allocate_struct_function (gnu_stub_decl, false);
set_cfun (NULL);
begin_subprog_body (gnu_stub_decl); begin_subprog_body (gnu_stub_decl);
gnat_pushlevel ();
start_stmt_group (); start_stmt_group ();
gnat_pushlevel ();
/* Loop over the parameters of the stub and translate any of them /* Loop over the parameters of the stub and translate any of them
passed by descriptor into a by reference one. */ passed by descriptor into a by reference one. */
...@@ -3258,8 +3262,6 @@ build_function_stub (tree gnu_subprog, Entity_Id gnat_subprog) ...@@ -3258,8 +3262,6 @@ build_function_stub (tree gnu_subprog, Entity_Id gnat_subprog)
VEC_safe_push (tree, gc, gnu_param_vec, gnu_param); VEC_safe_push (tree, gc, gnu_param_vec, gnu_param);
} }
gnu_body = end_stmt_group ();
/* Invoke the internal subprogram. */ /* Invoke the internal subprogram. */
gnu_subprog_addr = build1 (ADDR_EXPR, build_pointer_type (gnu_subprog_type), gnu_subprog_addr = build1 (ADDR_EXPR, build_pointer_type (gnu_subprog_type),
gnu_subprog); gnu_subprog);
...@@ -3268,16 +3270,13 @@ build_function_stub (tree gnu_subprog, Entity_Id gnat_subprog) ...@@ -3268,16 +3270,13 @@ build_function_stub (tree gnu_subprog, Entity_Id gnat_subprog)
/* Propagate the return value, if any. */ /* Propagate the return value, if any. */
if (VOID_TYPE_P (TREE_TYPE (gnu_subprog_type))) if (VOID_TYPE_P (TREE_TYPE (gnu_subprog_type)))
append_to_statement_list (gnu_subprog_call, &gnu_body); add_stmt (gnu_subprog_call);
else else
append_to_statement_list (build_return_expr (DECL_RESULT (gnu_stub_decl), add_stmt (build_return_expr (DECL_RESULT (gnu_stub_decl),
gnu_subprog_call), gnu_subprog_call));
&gnu_body);
gnat_poplevel (); gnat_poplevel ();
end_subprog_body (end_stmt_group ());
allocate_struct_function (gnu_stub_decl, false);
end_subprog_body (gnu_body);
} }
/* Build a type to be used to represent an aliased object whose nominal type /* Build a type to be used to represent an aliased object whose nominal type
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment