From: Jason Merrill Date: Wed, 15 Mar 1995 21:48:01 +0000 (+0000) Subject: Handle compilation of nested functions from another scope. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a0dabda52b4085f759f495d3e60b6583d7b3668c;p=gcc.git Handle compilation of nested functions from another scope. From-SVN: r9185 --- diff --git a/gcc/function.c b/gcc/function.c index 4ee042b373b..442b506b9e2 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -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. */ diff --git a/gcc/function.h b/gcc/function.h index 03186ade9a6..e8b32e80e41 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -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; diff --git a/gcc/tree.c b/gcc/tree.c index cdbba0ce2a9..166ca4bfc36 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -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;