]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
decl2.c (defer_fn): Set DECL_DEFER_OUTPUT.
authorJan Hubicka <jh@suse.cz>
Wed, 2 Jul 2003 00:12:10 +0000 (02:12 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Wed, 2 Jul 2003 00:12:10 +0000 (00:12 +0000)
* decl2.c (defer_fn): Set DECL_DEFER_OUTPUT.
(finish-file): Do not process function with DECL_DEFER_OUTPUT clear;
clear DECL_DEFER_OUTPUT once function is processed; avoid flags
massaging.

* cp-tree.h (DECL_NEEDED_P): Support unit-at-a-time
(expand_or_defer_fn): Declare.
(lower_function): Declare.
* decl.c (start_cleanup_fn): Use expand_or_defer_fn.
* decl2.c: Include cgraph.h and varpool.h
(maybe_emit_vtables):  Make explicit instantations as needed.
(mark_member_pointers, lower_function): New functions.
(finish_file): Do unit-at-a-time.
* method.c (synthesize_method): Use expand_or_defer_fn.
* optimize.c (maybe_clone_body): Use expand_or_defer_fn.
* parser.c (cp_parser_function_definition_after_decl): Use
expand_or_defer_fn.
* pt.c (instantiate_decl): Likewise.
* semantics.c: Include cgraph.h
(expand_or_defer_fn): Break out from ...
(expand_body): ... here; deal with unit-at-a-time.
* cp-lang.c (LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION,
LANG_HOOKS_CALLGRAPH_LOWER_FUNCTION): Define.

From-SVN: r68801

12 files changed:
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/call.c
gcc/cp/cp-lang.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/method.c
gcc/cp/optimize.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c

index c2d454561aea0e2864d6723b6a1c7205581f8944..1c0585073d6ee1301c364e6599e4e0c42c7be8ea 100644 (file)
@@ -1,3 +1,29 @@
+Wed Jul  2 00:36:48 CEST 2003  Jan Hubicka  <jh@suse.cz>
+
+       * decl2.c (defer_fn): Set DECL_DEFER_OUTPUT.
+       (finish-file): Do not process function with DECL_DEFER_OUTPUT clear;
+       clear DECL_DEFER_OUTPUT once function is processed; avoid flags
+       massaging.
+
+       * cp-tree.h (DECL_NEEDED_P): Support unit-at-a-time
+       (expand_or_defer_fn): Declare.
+       (lower_function): Declare.
+       * decl.c (start_cleanup_fn): Use expand_or_defer_fn.
+       * decl2.c: Include cgraph.h and varpool.h
+       (maybe_emit_vtables):  Make explicit instantations as needed.
+       (mark_member_pointers, lower_function): New functions.
+       (finish_file): Do unit-at-a-time.
+       * method.c (synthesize_method): Use expand_or_defer_fn.
+       * optimize.c (maybe_clone_body): Use expand_or_defer_fn.
+       * parser.c (cp_parser_function_definition_after_decl): Use
+       expand_or_defer_fn.
+       * pt.c (instantiate_decl): Likewise.
+       * semantics.c: Include cgraph.h
+       (expand_or_defer_fn): Break out from ...
+       (expand_body): ... here; deal with unit-at-a-time.
+       * cp-lang.c (LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION,
+       LANG_HOOKS_CALLGRAPH_LOWER_FUNCTION): Define.
+
 2003-07-01  Mark Mitchell  <mark@codesourcery.com>
 
        * call.c (resolve_scoped_fn_name): Return error_mark_node for
index 2ca563467a01d135ec78e4b9f5a45b385e70d02d..d6b871a981d07d1ba7cbd46374cf6ad554c5fb65 100644 (file)
@@ -240,7 +240,7 @@ cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h stack.h \
   cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h c-pragma.h \
   debug.h gt-cp-decl.h gtype-cp.h timevar.h
 cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \
-  output.h except.h toplev.h $(RTL_H) c-common.h gt-cp-decl2.h
+  output.h except.h toplev.h $(RTL_H) c-common.h gt-cp-decl2.h cgraph.h
 cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h output.h $(TM_P_H) \
    diagnostic.h
 cp/typeck.o: cp/typeck.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
@@ -271,7 +271,7 @@ cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h diagnostic.h \
   gt-cp-repo.h
 cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) cp/lex.h except.h toplev.h \
   flags.h debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \
-  tree-inline.h
+  tree-inline.h cgraph.h
 cp/dump.o: cp/dump.c $(CXX_TREE_H) $(TM_H) tree-dump.h
 cp/optimize.o: cp/optimize.c $(CXX_TREE_H) $(TM_H) rtl.h integrate.h insn-config.h \
   input.h $(PARAMS_H) debug.h tree-inline.h
index 6aab2ad3ada0bfefcd7df3fc921f0700d4ae5572..6e5bc8f5d4943c654d0457af6464d3af229b26d9 100644 (file)
@@ -2749,7 +2749,7 @@ build_user_type_conversion (tree totype, tree expr, int flags)
 tree
 resolve_scoped_fn_name (tree scope, tree name)
 {
-  tree fn;
+  tree fn = NULL_TREE;
   tree template_args = NULL_TREE;
   bool is_template_id = TREE_CODE (name) == TEMPLATE_ID_EXPR;
   
index f26317bb22f501ba1e154623efcb1b6130603fbd..78a4e6ba3e38602eace9c690f01313619aeb26b5 100644 (file)
@@ -150,6 +150,11 @@ static bool cp_var_mod_type_p (tree);
 #undef LANG_HOOKS_PREPARE_ASSEMBLE_VARIABLE 
 #define LANG_HOOKS_PREPARE_ASSEMBLE_VARIABLE prepare_assemble_variable
 
+#undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
+#define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION expand_body
+#undef LANG_HOOKS_CALLGRAPH_LOWER_FUNCTION
+#define LANG_HOOKS_CALLGRAPH_LOWER_FUNCTION lower_function
+
 #undef LANG_HOOKS_MAKE_TYPE
 #define LANG_HOOKS_MAKE_TYPE cxx_make_type
 #undef LANG_HOOKS_TYPE_FOR_MODE
index aec80b3895cfb51d4128aaaf3052385550544a5d..8612b8cee20a22ca305262466d2dc7400533864f 100644 (file)
@@ -1746,7 +1746,7 @@ struct lang_decl GTY(())
   ((at_eof && TREE_PUBLIC (DECL) && !DECL_COMDAT (DECL))       \
    || (DECL_ASSEMBLER_NAME_SET_P (DECL)                                \
        && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL))) \
-   || (flag_syntax_only && TREE_USED (DECL)))
+   || (((flag_syntax_only || flag_unit_at_a_time) && TREE_USED (DECL))))
 
 /* For a FUNCTION_DECL or a VAR_DECL, the language linkage for the
    declaration.  Some entities (like a member function in a local
@@ -3800,6 +3800,7 @@ extern tree get_guard (tree);
 extern tree get_guard_cond (tree);
 extern tree set_guard (tree);
 extern void prepare_assemble_variable (tree);
+extern void lower_function (tree);
 
 extern void cp_error_at                (const char *msgid, ...);
 extern void cp_warning_at      (const char *msgid, ...);
@@ -4151,6 +4152,7 @@ extern void clear_out_block                     (void);
 extern tree begin_global_stmt_expr              (void);
 extern tree finish_global_stmt_expr             (tree);
 extern tree check_template_template_default_arg (tree);
+extern void expand_or_defer_fn                 (tree);
 
 /* in tree.c */
 extern void lang_check_failed                  (const char *, int,
index 24e8f787569f04960b3b62a6efadfc27c82d95c3..863a21dced1bac484aea84e2f7c920dac29a7354 100644 (file)
@@ -8446,7 +8446,7 @@ start_cleanup_fn (void)
 static void
 end_cleanup_fn (void)
 {
-  expand_body (finish_function (0));
+  expand_or_defer_fn (finish_function (0));
 
   pop_from_top_level ();
 }
index d27bacd6018bda38aa8123f060789d60c53ce3be..a440c064478ebfc9ebe28dd59c5d5762daae0692 100644 (file)
@@ -46,6 +46,8 @@ Boston, MA 02111-1307, USA.  */
 #include "cpplib.h"
 #include "target.h"
 #include "c-common.h"
+#include "cgraph.h"
+#include "tree-inline.h"
 extern cpp_reader *parse_in;
 
 /* This structure contains information about the initializations
@@ -1187,6 +1189,7 @@ defer_fn (tree fn)
   if (DECL_DEFERRED_FN (fn))
     return;
   DECL_DEFERRED_FN (fn) = 1;
+  DECL_DEFER_OUTPUT (fn) = 1;
   if (!deferred_fns)
     VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
 
@@ -1671,6 +1674,11 @@ maybe_emit_vtables (tree ctype)
       /* Write it out.  */
       import_export_vtable (vtbl, ctype, 1);
       mark_vtable_entries (vtbl);
+
+      /* If we know that DECL is needed, mark it as such for the varpool.  */
+      if (CLASSTYPE_EXPLICIT_INSTANTIATION (ctype))
+       cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl));
+
       if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
        store_init_value (vtbl, DECL_INITIAL (vtbl));
 
@@ -2010,7 +2018,7 @@ finish_objects (int method_type, int initp, tree body)
   /* Finish up.  */
   finish_compound_stmt (/*has_no_scope=*/0, body);
   fn = finish_function (0);
-  expand_body (fn);
+  expand_or_defer_fn (fn);
 
   /* When only doing semantic analysis, and no RTL generation, we
      can't call functions that directly emit assembly code; there is
@@ -2163,7 +2171,7 @@ finish_static_storage_duration_function (tree body)
 {
   /* Close out the function.  */
   finish_compound_stmt (/*has_no_scope=*/0, body);
-  expand_body (finish_function (0));
+  expand_or_defer_fn (finish_function (0));
 }
 
 /* Return the information about the indicated PRIORITY level.  If no
@@ -2550,6 +2558,26 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
   return 0;
 }
 
+/* Callgraph code does not understand the member pointers.  Mark the methods
+   referenced as used.  */
+static tree
+mark_member_pointers (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
+                     void *data ATTRIBUTE_UNUSED)
+{
+  if (TREE_CODE (*tp) == PTRMEM_CST)
+    cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (*tp)), 1);
+  return 0;
+}
+
+/* Called via LANGHOOK_CALLGRAPH_LOWER_FUNCTION.  It is supposed to lower
+   frontend specific constructs that would otherwise confuse the middle end.  */
+void
+lower_function (tree fn)
+{
+  walk_tree_without_duplicates (&DECL_SAVED_TREE (fn), mark_member_pointers,
+                               NULL);
+}
+
 /* This routine is called from the last rule in yyparse ().
    Its job is to create all the code needed to initialize and
    destroy the global aggregates.  We do the destruction
@@ -2787,20 +2815,16 @@ finish_file ()
          if (!DECL_EXTERNAL (decl)
              && DECL_NEEDED_P (decl)
              && DECL_SAVED_TREE (decl)
-             && !TREE_ASM_WRITTEN (decl))
+             && !TREE_ASM_WRITTEN (decl)
+             && (!flag_unit_at_a_time 
+                 || !cgraph_node (decl)->local.finalized))
            {
-             int saved_not_really_extern;
-
-             /* When we call finish_function in expand_body, it will
-                try to reset DECL_NOT_REALLY_EXTERN so we save and
-                restore it here.  */
-             saved_not_really_extern = DECL_NOT_REALLY_EXTERN (decl);
+             /* We will output the function; no longer consider it in this
+                loop.  */
+             DECL_DEFER_OUTPUT (decl) = 0;
              /* Generate RTL for this function now that we know we
                 need it.  */
-             expand_body (decl);
-             /* Undo the damage done by finish_function.  */
-             DECL_EXTERNAL (decl) = 0;
-             DECL_NOT_REALLY_EXTERN (decl) = saved_not_really_extern;
+             expand_or_defer_fn (decl);
              /* If we're compiling -fsyntax-only pretend that this
                 function has been written out so that we don't try to
                 expand it again.  */
@@ -2810,10 +2834,6 @@ finish_file ()
            }
        }
 
-      if (deferred_fns_used
-         && wrapup_global_declarations (&VARRAY_TREE (deferred_fns, 0),
-                                        deferred_fns_used))
-       reconsider = true;
       if (walk_namespaces (wrapup_globals_for_namespace, /*data=*/0))
        reconsider = true;
 
@@ -2883,6 +2903,12 @@ finish_file ()
      linkage now.  */
   pop_lang_context ();
 
+  if (flag_unit_at_a_time)
+    {
+      cgraph_finalize_compilation_unit ();
+      cgraph_optimize ();
+    }
+
   /* Now, issue warnings about static, but not defined, functions,
      etc., and emit debugging information.  */
   walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider);
index cb2c864bfca89428c9ea50a8e24a3115f98cd3d7..e179d1532fe0783f9df9d7d8919c809be98ac37d 100644 (file)
@@ -581,7 +581,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
       /* Re-enable access control.  */
       pop_deferring_access_checks ();
 
-      expand_body (finish_function (0));
+      expand_or_defer_fn (finish_function (0));
     }
 
   pop_from_top_level ();
@@ -862,7 +862,7 @@ synthesize_method (tree fndecl)
     }
 
   finish_function_body (stmt);
-  expand_body (finish_function (0));
+  expand_or_defer_fn (finish_function (0));
 
   extract_interface_info ();
   if (! context)
index b5d0f8f28ded297d98fdaaf95ccbe401e216488a..4be829e818bdc52e4ea0e177d0e526182dcffdb1 100644 (file)
@@ -265,7 +265,7 @@ maybe_clone_body (tree fn)
       /* Now, expand this function into RTL, if appropriate.  */
       finish_function (0);
       BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
-      expand_body (clone);
+      expand_or_defer_fn (clone);
       pop_from_top_level ();
     }
 
index 173a62f7cff4f6418c017e75093889144d3c7a34..3654adbe0a84509d9a41eb4cd2e199a821e6a7a5 100644 (file)
@@ -13855,7 +13855,7 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
   fn = finish_function ((ctor_initializer_p ? 1 : 0) | 
                        (inline_p ? 2 : 0));
   /* Generate code for it, if necessary.  */
-  expand_body (fn);
+  expand_or_defer_fn (fn);
   /* Restore the saved values.  */
   parser->in_unbraced_linkage_specification_p 
     = saved_in_unbraced_linkage_specification_p;
index 2d80847c54938bf3b2858e1870c52248c07698b4..43fc5ab08609ba1f82acccf7ec88fedddc9e65e1 100644 (file)
@@ -10942,7 +10942,7 @@ instantiate_decl (tree d, int defer_ok)
 
       /* Finish the function.  */
       d = finish_function (0);
-      expand_body (d);
+      expand_or_defer_fn (d);
     }
 
   /* We're not deferring instantiation any more.  */
index a42443b94f65d1d279879ff12df65c1839a54a19..382bee509b9c6cba9f56c107cdb0436bf9ca0517 100644 (file)
@@ -41,6 +41,7 @@
 #include "output.h"
 #include "timevar.h"
 #include "debug.h"
+#include "cgraph.h"
 
 /* There routines provide a modular interface to perform many parsing
    operations.  They may therefore be used during actual parsing, or
@@ -2279,69 +2280,9 @@ expand_body (tree fn)
 {
   location_t saved_loc;
   tree saved_function;
-
-  /* When the parser calls us after finishing the body of a template
-     function, we don't really want to expand the body.  When we're
-     processing an in-class definition of an inline function,
-     PROCESSING_TEMPLATE_DECL will no longer be set here, so we have
-     to look at the function itself.  */
-  if (processing_template_decl
-      || (DECL_LANG_SPECIFIC (fn) 
-         && DECL_TEMPLATE_INFO (fn)
-         && uses_template_parms (DECL_TI_ARGS (fn))))
-    {
-      /* Normally, collection only occurs in rest_of_compilation.  So,
-        if we don't collect here, we never collect junk generated
-        during the processing of templates until we hit a
-        non-template function.  */
-      ggc_collect ();
-      return;
-    }
-
-  /* Replace AGGR_INIT_EXPRs with appropriate CALL_EXPRs.  */
-  walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
-                               simplify_aggr_init_exprs_r,
-                               NULL);
-
-  /* If this is a constructor or destructor body, we have to clone
-     it.  */
-  if (maybe_clone_body (fn))
-    {
-      /* We don't want to process FN again, so pretend we've written
-        it out, even though we haven't.  */
-      TREE_ASM_WRITTEN (fn) = 1;
-      return;
-    }
-
-  /* There's no reason to do any of the work here if we're only doing
-     semantic analysis; this code just generates RTL.  */
-  if (flag_syntax_only)
-    return;
-
-  /* If possible, avoid generating RTL for this function.  Instead,
-     just record it as an inline function, and wait until end-of-file
-     to decide whether to write it out or not.  */
-  if (/* We have to generate RTL if it's not an inline function.  */
-      (DECL_INLINE (fn) || DECL_COMDAT (fn))
-      /* Or if we have to emit code for inline functions anyhow.  */
-      && !flag_keep_inline_functions
-      /* Or if we actually have a reference to the function.  */
-      && !DECL_NEEDED_P (fn))
-    {
-      /* Set DECL_EXTERNAL so that assemble_external will be called as
-        necessary.  We'll clear it again in finish_file.  */
-      if (!DECL_EXTERNAL (fn))
-       {
-         DECL_NOT_REALLY_EXTERN (fn) = 1;
-         DECL_EXTERNAL (fn) = 1;
-       }
-      /* Remember this function.  In finish_file we'll decide if
-        we actually need to write this function out.  */
-      defer_fn (fn);
-      /* Let the back-end know that this function exists.  */
-      (*debug_hooks->deferred_inline_function) (fn);
-      return;
-    }
+  
+  if (flag_unit_at_a_time && !cgraph_global_info_ready)
+    abort ();
 
   /* Compute the appropriate object-file linkage for inline
      functions.  */
@@ -2413,6 +2354,108 @@ expand_body (tree fn)
   emit_associated_thunks (fn);
 }
 
+/* Generate RTL for FN.  */
+
+void
+expand_or_defer_fn (fn)
+     tree fn;
+{
+  /* When the parser calls us after finishing the body of a template
+     function, we don't really want to expand the body.  When we're
+     processing an in-class definition of an inline function,
+     PROCESSING_TEMPLATE_DECL will no longer be set here, so we have
+     to look at the function itself.  */
+  if (processing_template_decl
+      || (DECL_LANG_SPECIFIC (fn) 
+         && DECL_TEMPLATE_INFO (fn)
+         && uses_template_parms (DECL_TI_ARGS (fn))))
+    {
+      /* Normally, collection only occurs in rest_of_compilation.  So,
+        if we don't collect here, we never collect junk generated
+        during the processing of templates until we hit a
+        non-template function.  */
+      ggc_collect ();
+      return;
+    }
+
+  /* Replace AGGR_INIT_EXPRs with appropriate CALL_EXPRs.  */
+  walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
+                               simplify_aggr_init_exprs_r,
+                               NULL);
+
+  /* If this is a constructor or destructor body, we have to clone
+     it.  */
+  if (maybe_clone_body (fn))
+    {
+      /* We don't want to process FN again, so pretend we've written
+        it out, even though we haven't.  */
+      TREE_ASM_WRITTEN (fn) = 1;
+      return;
+    }
+
+  /* There's no reason to do any of the work here if we're only doing
+     semantic analysis; this code just generates RTL.  */
+  if (flag_syntax_only)
+    return;
+
+  if (flag_unit_at_a_time && cgraph_global_info_ready)
+    abort ();
+
+  if (flag_unit_at_a_time && !cgraph_global_info_ready)
+    {
+      if (at_eof)
+       {
+         /* Compute the appropriate object-file linkage for inline
+            functions.  */
+         if (DECL_DECLARED_INLINE_P (fn))
+           import_export_decl (fn);
+         cgraph_finalize_function (fn, DECL_SAVED_TREE (fn));
+       }
+      else
+       {
+         if (!DECL_EXTERNAL (fn))
+           {
+             DECL_NOT_REALLY_EXTERN (fn) = 1;
+             DECL_EXTERNAL (fn) = 1;
+           }
+         /* Remember this function.  In finish_file we'll decide if
+            we actually need to write this function out.  */
+         defer_fn (fn);
+         /* Let the back-end know that this function exists.  */
+         (*debug_hooks->deferred_inline_function) (fn);
+       }
+      return;
+    }
+
+
+  /* If possible, avoid generating RTL for this function.  Instead,
+     just record it as an inline function, and wait until end-of-file
+     to decide whether to write it out or not.  */
+  if (/* We have to generate RTL if it's not an inline function.  */
+      (DECL_INLINE (fn) || DECL_COMDAT (fn))
+      /* Or if we have to emit code for inline functions anyhow.  */
+      && !flag_keep_inline_functions
+      /* Or if we actually have a reference to the function.  */
+      && !DECL_NEEDED_P (fn))
+    {
+      /* Set DECL_EXTERNAL so that assemble_external will be called as
+        necessary.  We'll clear it again in finish_file.  */
+      if (!DECL_EXTERNAL (fn))
+       {
+         DECL_NOT_REALLY_EXTERN (fn) = 1;
+         DECL_EXTERNAL (fn) = 1;
+       }
+      /* Remember this function.  In finish_file we'll decide if
+        we actually need to write this function out.  */
+      defer_fn (fn);
+      /* Let the back-end know that this function exists.  */
+      (*debug_hooks->deferred_inline_function) (fn);
+      return;
+    }
+
+  expand_body (fn);
+}
+
 /* Helper function for walk_tree, used by finish_function to override all
    the RETURN_STMTs and pertinent CLEANUP_STMTs for the named return
    value optimization.  */