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)
since this function knows only about language-independent variables. */
void
push_function_context_to (toplevel)
int toplevel;
push_function_context_to (context)
tree context;
{
struct function *p = (struct function *) xmalloc (sizeof (struct function));
......@@ -481,6 +481,7 @@ push_function_context_to (toplevel)
p->calls_alloca = current_function_calls_alloca;
p->has_nonlocal_label = current_function_has_nonlocal_label;
p->has_nonlocal_goto = current_function_has_nonlocal_goto;
p->contains_functions = current_function_contains_functions;
p->args_size = current_function_args_size;
p->pretend_args_size = current_function_pretend_args_size;
p->arg_offset_rtx = current_function_arg_offset_rtx;
......@@ -514,7 +515,7 @@ push_function_context_to (toplevel)
p->fixup_var_refs_queue = 0;
p->epilogue_delay_list = current_function_epilogue_delay_list;
save_tree_status (p, toplevel);
save_tree_status (p, context);
save_storage_status (p);
save_emit_status (p);
init_emit ();
......@@ -529,15 +530,15 @@ push_function_context_to (toplevel)
void
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.
This function is called from language-specific code. */
void
pop_function_context_from (toplevel)
int toplevel;
pop_function_context_from (context)
tree context;
{
struct function *p = outer_function_chain;
......@@ -554,8 +555,9 @@ pop_function_context_from (toplevel)
current_function_calls_alloca = p->calls_alloca;
current_function_has_nonlocal_label = p->has_nonlocal_label;
current_function_has_nonlocal_goto = p->has_nonlocal_goto;
if (! toplevel)
current_function_contains_functions = 1;
current_function_contains_functions
= p->contains_functions || p->inline_obstacks
|| context == current_function_decl;
current_function_args_size = p->args_size;
current_function_pretend_args_size = p->pretend_args_size;
current_function_arg_offset_rtx = p->arg_offset_rtx;
......@@ -589,7 +591,7 @@ pop_function_context_from (toplevel)
current_function_epilogue_delay_list = p->epilogue_delay_list;
reg_renumber = 0;
restore_tree_status (p, toplevel);
restore_tree_status (p);
restore_storage_status (p);
restore_expr_status (p);
restore_emit_status (p);
......@@ -616,7 +618,7 @@ pop_function_context_from (toplevel)
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. */
......
......@@ -47,6 +47,14 @@ struct 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
describing the status of the current function. */
......@@ -67,6 +75,7 @@ struct function
int calls_alloca;
int has_nonlocal_label;
int has_nonlocal_goto;
int contains_functions;
rtx nonlocal_goto_handler_slot;
rtx nonlocal_goto_stack_level;
tree nonlocal_labels;
......@@ -158,6 +167,7 @@ struct function
struct obstack *expression_obstack;
struct obstack *saveable_obstack;
struct obstack *rtl_obstack;
struct simple_obstack_stack *inline_obstacks;
/* For integrate.c. */
int uses_const_pool;
......
......@@ -66,6 +66,17 @@ struct obstack *function_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
in this obstack, and all are freed at the end of the function.
For top-level functions, this is temporary_obstack.
......@@ -315,12 +326,15 @@ gcc_obstack_init (obstack)
}
/* 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
save_tree_status (p, toplevel)
save_tree_status (p, context)
struct function *p;
int toplevel;
tree context;
{
p->all_types_permanent = all_types_permanent;
p->momentary_stack = momentary_stack;
......@@ -333,16 +347,42 @@ save_tree_status (p, toplevel)
p->expression_obstack = expression_obstack;
p->saveable_obstack = saveable_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
obstack of the enclosing function since they can't possibly be needed
once it has returned. */
function_maybepermanent_obstack = function_obstack;
maybepermanent_firstobj
= (char *) obstack_finish (function_maybepermanent_obstack);
}
/* We're compiling a function which isn't nested in the current
function. We need to create a new maybepermanent_obstack for this
function, since it can't go onto any of the existing obstacks. */
struct simple_obstack_stack **head;
struct simple_obstack_stack *current;
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));
gcc_obstack_init (function_obstack);
......@@ -359,26 +399,22 @@ save_tree_status (p, toplevel)
This is used after a nested function. */
void
restore_tree_status (p, toplevel)
restore_tree_status (p)
struct function *p;
int toplevel;
{
all_types_permanent = p->all_types_permanent;
momentary_stack = p->momentary_stack;
obstack_free (&momentary_obstack, momentary_function_firstobj);
if (! toplevel)
{
/* 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
the compilation of a nested function if we expect it to survive
past the nested function's end. */
obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj);
}
/* 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
the compilation of a nested function if we expect it to survive
past the nested function's end. */
obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj);
obstack_free (function_obstack, 0);
free (function_obstack);
......@@ -392,6 +428,7 @@ restore_tree_status (p, toplevel)
expression_obstack = p->expression_obstack;
saveable_obstack = p->saveable_obstack;
rtl_obstack = p->rtl_obstack;
inline_obstacks = p->inline_obstacks;
}
/* Start allocating on the temporary (per function) obstack.
......@@ -408,6 +445,7 @@ temporary_allocation ()
expression_obstack = function_obstack;
rtl_obstack = saveable_obstack = function_maybepermanent_obstack;
momentary_stack = 0;
inline_obstacks = 0;
}
/* Start allocating on the permanent obstack but don't
......@@ -535,6 +573,17 @@ permanent_allocation (function_end)
obstack_free (function_maybepermanent_obstack, maybepermanent_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;
expression_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