diff options
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 97 |
1 files changed, 73 insertions, 24 deletions
@@ -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; |