OSDN Git Service

Handle compilation of nested functions from another scope.
authormerrill <merrill@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 15 Mar 1995 21:48:01 +0000 (21:48 +0000)
committermerrill <merrill@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 15 Mar 1995 21:48:01 +0000 (21:48 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@9185 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/function.c
gcc/function.h
gcc/tree.c

index 4ee042b..442b506 100644 (file)
@@ -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);
 }
 \f
 /* Allocate fixed slots in the stack frame of the current function.  */
index 03186ad..e8b32e8 100644 (file)
@@ -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;
+};
 \f
 /* 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;
index cdbba0c..166ca4b 100644 (file)
@@ -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;
 }
 \f
 /* 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;