Commit a0dabda5 by Jason Merrill

Handle compilation of nested functions from another scope.

From-SVN: r9185
parent ea9be077
...@@ -462,8 +462,8 @@ find_function_data (decl) ...@@ -462,8 +462,8 @@ find_function_data (decl)
since this function knows only about language-independent variables. */ since this function knows only about language-independent variables. */
void void
push_function_context_to (toplevel) push_function_context_to (context)
int toplevel; tree context;
{ {
struct function *p = (struct function *) xmalloc (sizeof (struct function)); struct function *p = (struct function *) xmalloc (sizeof (struct function));
...@@ -481,6 +481,7 @@ push_function_context_to (toplevel) ...@@ -481,6 +481,7 @@ push_function_context_to (toplevel)
p->calls_alloca = current_function_calls_alloca; p->calls_alloca = current_function_calls_alloca;
p->has_nonlocal_label = current_function_has_nonlocal_label; p->has_nonlocal_label = current_function_has_nonlocal_label;
p->has_nonlocal_goto = current_function_has_nonlocal_goto; p->has_nonlocal_goto = current_function_has_nonlocal_goto;
p->contains_functions = current_function_contains_functions;
p->args_size = current_function_args_size; p->args_size = current_function_args_size;
p->pretend_args_size = current_function_pretend_args_size; p->pretend_args_size = current_function_pretend_args_size;
p->arg_offset_rtx = current_function_arg_offset_rtx; p->arg_offset_rtx = current_function_arg_offset_rtx;
...@@ -514,7 +515,7 @@ push_function_context_to (toplevel) ...@@ -514,7 +515,7 @@ push_function_context_to (toplevel)
p->fixup_var_refs_queue = 0; p->fixup_var_refs_queue = 0;
p->epilogue_delay_list = current_function_epilogue_delay_list; p->epilogue_delay_list = current_function_epilogue_delay_list;
save_tree_status (p, toplevel); save_tree_status (p, context);
save_storage_status (p); save_storage_status (p);
save_emit_status (p); save_emit_status (p);
init_emit (); init_emit ();
...@@ -529,15 +530,15 @@ push_function_context_to (toplevel) ...@@ -529,15 +530,15 @@ push_function_context_to (toplevel)
void void
push_function_context () push_function_context ()
{ {
push_function_context_to (0); push_function_context_to (current_function_decl);
} }
/* Restore the last saved context, at the end of a nested function. /* Restore the last saved context, at the end of a nested function.
This function is called from language-specific code. */ This function is called from language-specific code. */
void void
pop_function_context_from (toplevel) pop_function_context_from (context)
int toplevel; tree context;
{ {
struct function *p = outer_function_chain; struct function *p = outer_function_chain;
...@@ -554,8 +555,9 @@ pop_function_context_from (toplevel) ...@@ -554,8 +555,9 @@ pop_function_context_from (toplevel)
current_function_calls_alloca = p->calls_alloca; current_function_calls_alloca = p->calls_alloca;
current_function_has_nonlocal_label = p->has_nonlocal_label; current_function_has_nonlocal_label = p->has_nonlocal_label;
current_function_has_nonlocal_goto = p->has_nonlocal_goto; current_function_has_nonlocal_goto = p->has_nonlocal_goto;
if (! toplevel) current_function_contains_functions
current_function_contains_functions = 1; = p->contains_functions || p->inline_obstacks
|| context == current_function_decl;
current_function_args_size = p->args_size; current_function_args_size = p->args_size;
current_function_pretend_args_size = p->pretend_args_size; current_function_pretend_args_size = p->pretend_args_size;
current_function_arg_offset_rtx = p->arg_offset_rtx; current_function_arg_offset_rtx = p->arg_offset_rtx;
...@@ -589,7 +591,7 @@ pop_function_context_from (toplevel) ...@@ -589,7 +591,7 @@ pop_function_context_from (toplevel)
current_function_epilogue_delay_list = p->epilogue_delay_list; current_function_epilogue_delay_list = p->epilogue_delay_list;
reg_renumber = 0; reg_renumber = 0;
restore_tree_status (p, toplevel); restore_tree_status (p);
restore_storage_status (p); restore_storage_status (p);
restore_expr_status (p); restore_expr_status (p);
restore_emit_status (p); restore_emit_status (p);
...@@ -616,7 +618,7 @@ pop_function_context_from (toplevel) ...@@ -616,7 +618,7 @@ pop_function_context_from (toplevel)
void pop_function_context () void pop_function_context ()
{ {
pop_function_context_from (0); pop_function_context_from (current_function_decl);
} }
/* Allocate fixed slots in the stack frame of the current function. */ /* Allocate fixed slots in the stack frame of the current function. */
......
...@@ -47,6 +47,14 @@ struct sequence_stack ...@@ -47,6 +47,14 @@ struct sequence_stack
}; };
extern struct sequence_stack *sequence_stack; extern struct sequence_stack *sequence_stack;
/* Stack of single obstacks. */
struct simple_obstack_stack
{
struct obstack *obstack;
struct simple_obstack_stack *next;
};
/* This structure can save all the important global and static variables /* This structure can save all the important global and static variables
describing the status of the current function. */ describing the status of the current function. */
...@@ -67,6 +75,7 @@ struct function ...@@ -67,6 +75,7 @@ struct function
int calls_alloca; int calls_alloca;
int has_nonlocal_label; int has_nonlocal_label;
int has_nonlocal_goto; int has_nonlocal_goto;
int contains_functions;
rtx nonlocal_goto_handler_slot; rtx nonlocal_goto_handler_slot;
rtx nonlocal_goto_stack_level; rtx nonlocal_goto_stack_level;
tree nonlocal_labels; tree nonlocal_labels;
...@@ -158,6 +167,7 @@ struct function ...@@ -158,6 +167,7 @@ struct function
struct obstack *expression_obstack; struct obstack *expression_obstack;
struct obstack *saveable_obstack; struct obstack *saveable_obstack;
struct obstack *rtl_obstack; struct obstack *rtl_obstack;
struct simple_obstack_stack *inline_obstacks;
/* For integrate.c. */ /* For integrate.c. */
int uses_const_pool; int uses_const_pool;
......
...@@ -66,6 +66,17 @@ struct obstack *function_maybepermanent_obstack; ...@@ -66,6 +66,17 @@ struct obstack *function_maybepermanent_obstack;
struct obstack maybepermanent_obstack; struct obstack maybepermanent_obstack;
/* This is a list of function_maybepermanent_obstacks for top-level inline
functions that are compiled in the middle of compiling other functions. */
struct simple_obstack_stack *toplev_inline_obstacks;
/* This is a list of function_maybepermanent_obstacks for inline functions
nested in the current function that were compiled in the middle of
compiling other functions. */
struct simple_obstack_stack *inline_obstacks;
/* The contents of the current function definition are allocated /* The contents of the current function definition are allocated
in this obstack, and all are freed at the end of the function. in this obstack, and all are freed at the end of the function.
For top-level functions, this is temporary_obstack. For top-level functions, this is temporary_obstack.
...@@ -315,12 +326,15 @@ gcc_obstack_init (obstack) ...@@ -315,12 +326,15 @@ gcc_obstack_init (obstack)
} }
/* Save all variables describing the current status into the structure *P. /* Save all variables describing the current status into the structure *P.
This is used before starting a nested function. */ This is used before starting a nested function.
CONTEXT is the decl_function_context for the function we're about to
compile; if it isn't current_function_decl, we have to play some games. */
void void
save_tree_status (p, toplevel) save_tree_status (p, context)
struct function *p; struct function *p;
int toplevel; tree context;
{ {
p->all_types_permanent = all_types_permanent; p->all_types_permanent = all_types_permanent;
p->momentary_stack = momentary_stack; p->momentary_stack = momentary_stack;
...@@ -333,16 +347,42 @@ save_tree_status (p, toplevel) ...@@ -333,16 +347,42 @@ save_tree_status (p, toplevel)
p->expression_obstack = expression_obstack; p->expression_obstack = expression_obstack;
p->saveable_obstack = saveable_obstack; p->saveable_obstack = saveable_obstack;
p->rtl_obstack = rtl_obstack; p->rtl_obstack = rtl_obstack;
p->inline_obstacks = inline_obstacks;
if (! toplevel) if (context == current_function_decl)
/* Objects that need to be saved in this function can be in the nonsaved
obstack of the enclosing function since they can't possibly be needed
once it has returned. */
function_maybepermanent_obstack = function_obstack;
else
{ {
/* Objects that need to be saved in this function can be in the nonsaved /* We're compiling a function which isn't nested in the current
obstack of the enclosing function since they can't possibly be needed function. We need to create a new maybepermanent_obstack for this
once it has returned. */ function, since it can't go onto any of the existing obstacks. */
function_maybepermanent_obstack = function_obstack; struct simple_obstack_stack **head;
maybepermanent_firstobj struct simple_obstack_stack *current;
= (char *) obstack_finish (function_maybepermanent_obstack);
} if (context == NULL_TREE)
head = &toplev_inline_obstacks;
else
{
struct function *f = find_function_data (context);
head = &f->inline_obstacks;
}
current = ((struct simple_obstack_stack *)
xmalloc (sizeof (struct simple_obstack_stack)));
current->obstack = (struct obstack *) xmalloc (sizeof (struct obstack));
function_maybepermanent_obstack = current->obstack;
gcc_obstack_init (function_maybepermanent_obstack);
current->next = *head;
*head = current;
}
maybepermanent_firstobj
= (char *) obstack_finish (function_maybepermanent_obstack);
function_obstack = (struct obstack *) xmalloc (sizeof (struct obstack)); function_obstack = (struct obstack *) xmalloc (sizeof (struct obstack));
gcc_obstack_init (function_obstack); gcc_obstack_init (function_obstack);
...@@ -359,26 +399,22 @@ save_tree_status (p, toplevel) ...@@ -359,26 +399,22 @@ save_tree_status (p, toplevel)
This is used after a nested function. */ This is used after a nested function. */
void void
restore_tree_status (p, toplevel) restore_tree_status (p)
struct function *p; struct function *p;
int toplevel;
{ {
all_types_permanent = p->all_types_permanent; all_types_permanent = p->all_types_permanent;
momentary_stack = p->momentary_stack; momentary_stack = p->momentary_stack;
obstack_free (&momentary_obstack, momentary_function_firstobj); obstack_free (&momentary_obstack, momentary_function_firstobj);
if (! toplevel) /* Free saveable storage used by the function just compiled and not
{ saved.
/* Free saveable storage used by the function just compiled and not
saved. CAUTION: This is in function_obstack of the containing function.
So we must be sure that we never allocate from that obstack during
CAUTION: This is in function_obstack of the containing function. the compilation of a nested function if we expect it to survive
So we must be sure that we never allocate from that obstack during past the nested function's end. */
the compilation of a nested function if we expect it to survive obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj);
past the nested function's end. */
obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj);
}
obstack_free (function_obstack, 0); obstack_free (function_obstack, 0);
free (function_obstack); free (function_obstack);
...@@ -392,6 +428,7 @@ restore_tree_status (p, toplevel) ...@@ -392,6 +428,7 @@ restore_tree_status (p, toplevel)
expression_obstack = p->expression_obstack; expression_obstack = p->expression_obstack;
saveable_obstack = p->saveable_obstack; saveable_obstack = p->saveable_obstack;
rtl_obstack = p->rtl_obstack; rtl_obstack = p->rtl_obstack;
inline_obstacks = p->inline_obstacks;
} }
/* Start allocating on the temporary (per function) obstack. /* Start allocating on the temporary (per function) obstack.
...@@ -408,6 +445,7 @@ temporary_allocation () ...@@ -408,6 +445,7 @@ temporary_allocation ()
expression_obstack = function_obstack; expression_obstack = function_obstack;
rtl_obstack = saveable_obstack = function_maybepermanent_obstack; rtl_obstack = saveable_obstack = function_maybepermanent_obstack;
momentary_stack = 0; momentary_stack = 0;
inline_obstacks = 0;
} }
/* Start allocating on the permanent obstack but don't /* Start allocating on the permanent obstack but don't
...@@ -535,6 +573,17 @@ permanent_allocation (function_end) ...@@ -535,6 +573,17 @@ permanent_allocation (function_end)
obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj); obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj);
obstack_free (&temp_decl_obstack, temp_decl_firstobj); obstack_free (&temp_decl_obstack, temp_decl_firstobj);
/* Free up the maybepermanent_obstacks for any of our nested functions
which were compiled at a lower level. */
while (inline_obstacks)
{
struct simple_obstack_stack *current = inline_obstacks;
inline_obstacks = current->next;
obstack_free (current->obstack, 0);
free (current->obstack);
free (current);
}
current_obstack = &permanent_obstack; current_obstack = &permanent_obstack;
expression_obstack = &permanent_obstack; expression_obstack = &permanent_obstack;
rtl_obstack = saveable_obstack = &permanent_obstack; rtl_obstack = saveable_obstack = &permanent_obstack;
......
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