This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[patch] Enable inline of forward-referenced fns in C


When the tree-based inliner moved out of the C++ parser, and was shared 
with
C, the ability to 'defer' a function was omitted.  This 'ability to
defer' allowed GCC C++ to inline a forward-referenced function. This
patch moves 'defer_fn' into the shared module tree-inline.c, making
it shared with the C parser, and accessible to other front-ends.

2001-10-30 Stuart Hastings <stuart@apple.com>

* c-common.c (at_eof): Moved here from cp/decl2.c, made global.
* c-common.h (at_eof): Same.
* c-decl.c (c_expand_body): invoke 'maybe_defer_fn'.
   (c_expand_body_unnested): Hookable, single parm interface to 
c_expand_body.
* c-lang.c (LANG_HOOKS_TREE_INLINING_EXPAND_BODY): New.
   (finish_file): Set 'at_eof', invoke 'flush_deferred_fns'.
* c-tree.h (c_expand_body_unnested): New, hookable version of 
'c_expand_body'.
* langhooks.c (tree_inlining_default_hook_expand_body): New.
* langhooks.h (tree_inlining_default_hook_expand_body): Install default 
hook.
* toplev.h (lang_hooks_for_tree_inlining): Add 
'LANG_HOOKS_TREE_INLINING_EXPAND_BODY'.
* tree-inline.c (debug.h): New include.
   (deferred_fns): Moved from cp/decl2.c, make global.
   (inlinable_function_p): Avoid examining inlining non-candidates in 
loop.
   (defer_fn): Moved here from cp/decl2.c. (flush_deferred_fns, 
maybe_defer_fn): New.
* tree-inline.h (varray.h) New include.
   (deferred_fns, deferred_fns_used, flush_deferred_fns, maybe_defer_fn): 
New.
* tree.h (struct tree_decl): Two bits moved here from cp/decl2.c:'struct 
lang_type'.
   (deferred, not_really_extern, DECL_DEFERED_FN, 
DECL_NOT_REALLY_EXTERNAL)
   (DECL_REALLY_EXTERN, DECL_NEEDED_P): Bits and macros moved here into
   'struct tree_decl' from cp/cp-tree.h:'struct lang_type'.
* cp/cp-lang.c (LANG_HOOKS_TREE_INLINING_EXPAND_BODY): New.
* cp/cp-tree.h (struct lang_type): Moved 'deferred', 'not_really_extern' 
bits,
   plus their macros, away to tree.h:'struct tree_decl'.
   (DECL_NEEDED_P, DECL_DEFERED_FN, DECL_EXTERNAL, DECL_NOT_REALLY_EXTERN)
   (DECL_REALLY_EXTERN): Moved away to tree.h:'struct tree_decl'.
* cp/decl2.c (tree-inline.h): New include.
   (deferred_fns, deferred_fns_used, at_eof, defer_fn): Moved away to 
tree-inline.c.
   (finish_file): Moved loop to tree-inline.c:'flush_deferred_fns'.
* cp/semantics.c (expand_body): Move 'defer_fn' logic to tree-
inline.c:'maybe_defer_fn'.

Index: gcc/gcc/c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.268
diff -c -d -r1.268 c-common.c
*** c-common.c  2001/10/28 20:09:00     1.268
--- c-common.c  2001/10/30 18:51:49
***************
*** 215,220 ****
--- 215,224 ----
      after the file has been completely parsed.  */
   void (*back_end_hook) PARAMS ((tree));

+ /* Nonzero if we're done parsing and into end-of-file activities.  */
+
+ int at_eof;
+
   /* Nonzero means the expression being parsed will never be evaluated.
      This is a count, since unevaluated expressions can nest.  */
   int skip_evaluation;
Index: gcc/gcc/c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.94
diff -c -d -r1.94 c-common.h
*** c-common.h  2001/10/28 20:09:00     1.94
--- c-common.h  2001/10/30 18:51:49
***************
*** 446,451 ****
--- 446,455 ----

   extern int warn_long_long;

+ /* Nonzero if we're done parsing and into end-of-file activities.  */
+
+ extern int at_eof;
+
   /* C types are partitioned into three subsets: object, function, and
      incomplete types.  */
   #define C_TYPE_OBJECT_P(type) \
Index: gcc/gcc/c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.258
diff -c -d -r1.258 c-decl.c
*** c-decl.c    2001/10/24 14:46:38     1.258
--- c-decl.c    2001/10/30 18:51:50
***************
*** 6808,6813 ****
--- 6808,6819 ----
     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 (!nested_p && maybe_defer_fn (fndecl))
+     return;
+
     timevar_push (TV_EXPAND);

     if (flag_inline_trees)
***************
*** 6963,6968 ****
--- 6969,6984 ----
     timevar_pop (TV_EXPAND);
   }


+ /* Hook for tree-inliner to invoke expand_body
+    like c_expand_body, but omits support for nesting.  */
+
+ void
+ c_expand_body_unnested (fndecl)
+      tree fndecl;
+ {
+   c_expand_body (fndecl, 0) ;
+ }
+
   /* Check the declarations given in a for-loop for satisfying the C99
      constraints.  */
   void
Index: gcc/gcc/c-lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-lang.c,v
retrieving revision 1.58
diff -c -d -r1.58 c-lang.c
*** c-lang.c    2001/10/23 18:51:01     1.58
--- c-lang.c    2001/10/30 18:51:50
***************
*** 68,73 ****
--- 68,75 ----
   #undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P
   #define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
     anon_aggr_type_p
+ #undef LANG_HOOKS_TREE_INLINING_EXPAND_BODY
+ #define LANG_HOOKS_TREE_INLINING_EXPAND_BODY c_expand_body_unnested

   /* Each front end provides its own.  */
   struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
***************
*** 264,269 ****
--- 266,272 ----
   void
   finish_file ()
   {
+   at_eof = 1 ;
   #ifndef ASM_OUTPUT_CONSTRUCTOR
     if (static_ctors)
       {
***************
*** 292,297 ****
--- 295,303 ----
     if (back_end_hook)
       (*back_end_hook) (getdecls ());

+   while (flush_deferred_fns ())
+     ;
+
     {
       int flags;
       FILE *stream = dump_begin (TDI_all, &flags);
Index: gcc/gcc/c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.71
diff -c -d -r1.71 c-tree.h
*** c-tree.h    2001/10/11 12:43:39     1.71
--- c-tree.h    2001/10/30 18:51:50
***************
*** 171,176 ****
--- 171,177 ----
   extern int  c_decode_option                     PARAMS ((int, 
char **));
   extern void c_mark_varargs                      PARAMS ((void));
   extern void check_for_loop_decls                PARAMS ((void));
+ extern void c_expand_body_unnested              PARAMS ((tree));
   extern tree check_identifier                    PARAMS ((tree, tree));
   extern void clear_parm_order                    PARAMS ((void));
   extern int  complete_array_type                 PARAMS ((tree, tree, 
int));
Index: gcc/gcc/langhooks.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/langhooks.c,v
retrieving revision 1.6
diff -c -d -r1.6 langhooks.c
*** langhooks.c 2001/10/25 17:56:51     1.6
--- langhooks.c 2001/10/30 18:51:50
***************
*** 190,192 ****
--- 190,201 ----
     return 0;
   }

+ /* lang_hooks.tree_inlinling.expand_body either generates RTL,
+    or defers the decision with defer_fn.  */
+ void
+ tree_inlining_default_hook_expand_body (t)
+      tree t ATTRIBUTE_UNUSED;
+ {
+   return ;
+ }
+
Index: gcc/gcc/langhooks.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/langhooks.h,v
retrieving revision 1.5
diff -c -d -r1.5 langhooks.h
*** langhooks.h 2001/10/25 17:56:51     1.5
--- langhooks.h 2001/10/30 18:51:50
***************
*** 67,72 ****
--- 67,73 ----
                                                                     
int *,
                                                                     
void *));
   int tree_inlining_default_hook_anon_aggr_type_p               PARAMS 
((tree));
+ void tree_inlining_default_hook_expand_body           PARAMS ((tree));

   /* Tree inlining hooks.  */
   #define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES \
***************
*** 85,90 ****
--- 86,93 ----
     tree_inlining_default_hook_copy_res_decl_for_inlining
   #define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
     tree_inlining_default_hook_anon_aggr_type_p
+ #define LANG_HOOKS_TREE_INLINING_EXPAND_BODY \
+   tree_inlining_default_hook_expand_body

   #define LANG_HOOKS_TREE_INLINING_INITIALIZER { \
     LANG_HOOKS_TREE_INLINING_WALK_SUBTREES, \
***************
*** 94,100 ****
     LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P, \
     LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P, \
     LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING, \
!   LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
   } \

   /* The whole thing.  The structure is defined in toplev.h.  */
--- 97,104 ----
     LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P, \
     LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P, \
     LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING, \
!   LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P, \
!   LANG_HOOKS_TREE_INLINING_EXPAND_BODY \
   } \

   /* The whole thing.  The structure is defined in toplev.h.  */
Index: gcc/gcc/toplev.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.h,v
retrieving revision 1.79
diff -c -d -r1.79 toplev.h
*** toplev.h    2001/10/25 17:56:52     1.79
--- toplev.h    2001/10/30 18:51:50
***************
*** 137,142 ****
--- 137,143 ----
                                                           void *, int *,
                                                           void *));
     int (*anon_aggr_type_p) PARAMS ((union tree_node *));
+   void (*expand_body) PARAMS((union tree_node *));
   };

   /* Language-specific hooks.  See langhooks.h for defaults.  */
Index: gcc/gcc/tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.8
diff -c -d -r1.8 tree-inline.c
*** tree-inline.c       2001/10/26 18:27:13     1.8
--- tree-inline.c       2001/10/30 18:51:50
***************
*** 34,39 ****
--- 34,40 ----
   #include "varray.h"
   #include "hashtab.h"
   #include "splay-tree.h"
+ #include "debug.h"

   /* This should be eventually be generalized to other languages, but
      this would require a shared function-as-trees infrastructure.  */
***************
*** 46,51 ****
--- 47,56 ----

   int flag_inline_trees = 0;

+ /* A list of functions which were declared inline, but which we
+    may need to emit outline anyway.  */
+ varray_type deferred_fns;
+
   /* To Do:

      o In order to make inlining-on-trees work, we pessimized
***************
*** 716,722 ****
       {
         size_t i;

!       for (i = 0; i < VARRAY_ACTIVE_SIZE (id->fns); ++i)
         if (VARRAY_TREE (id->fns, i) == fn)
           return 0;

--- 721,728 ----
       {
         size_t i;

!       /* If fn already in list, this is recursion.  Stop.  */
!       for (i = id->first_inlined_fn; i < VARRAY_ACTIVE_SIZE (id->fns); 
++i)
         if (VARRAY_TREE (id->fns, i) == fn)
           return 0;

***************
*** 1390,1393 ****
--- 1396,1511 ----

     /* Replace this SAVE_EXPR with the copy.  */
     *tp = (tree) n->value;
+ }
+

+ /* Defer the compilation of the FN until the end of compilation.  */
+
+ void
+ defer_fn (fn)
+      tree fn;
+ {
+   if (DECL_DEFERRED_FN (fn))
+     return;
+
+   DECL_DEFERRED_FN (fn) = 1;
+   if (!deferred_fns)
+     VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
+
+   VARRAY_PUSH_TREE (deferred_fns, fn);
+ }
+
+ /* revisit deferred function trees, synthesize/instantiate as required
+    returns nonzero if any fn un-deferred (ie any change), zero for no 
change  */
+
+ int
+ flush_deferred_fns ()
+ {
+   int i;
+   int reconsider = 0;
+
+   /* We lie to the back-end, pretending that some functions are
+        not defined when they really are.  This keeps these functions
+        from being put out unnecessarily.  But, we must stop lying
+        when the functions are referenced, or if they are not comdat
+        since they need to be put out now.  */
+   for (i = 0; i < deferred_fns_used; ++i)
+     {
+       tree decl = VARRAY_TREE (deferred_fns, i);
+
+       if (DECL_NOT_REALLY_EXTERN (decl)
+         && DECL_INITIAL (decl)
+         && DECL_NEEDED_P (decl))
+       DECL_EXTERNAL (decl) = 0;
+
+       /* If we're going to need to write this function out, and
+        there's already a body for it, create RTL for it now.
+        (There might be no body if this is a method we haven't
+        gotten around to synthesizing yet.)  */
+       if ( !DECL_EXTERNAL (decl)
+         && DECL_NEEDED_P (decl)
+         && DECL_SAVED_TREE (decl)
+         && !TREE_ASM_WRITTEN (decl))
+       {
+         int saved_not_really_extern;
+         int saved_flag_keep_inline_functions;
+
+         /* 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);
+         saved_flag_keep_inline_functions = flag_keep_inline_functions;
+         /* discourage expand_body from deferring this fn again */
+         flag_keep_inline_functions = 1;
+         /* Generate RTL for this function now that we know we
+            need it.  */
+         (*lang_hooks.tree_inlining.expand_body) (decl);
+         flag_keep_inline_functions = saved_flag_keep_inline_functions;
+         /* Undo the damage done by finish_function.  */
+         DECL_EXTERNAL (decl) = 0;
+         DECL_NOT_REALLY_EXTERN (decl) = saved_not_really_extern;
+         /* If we're compiling -fsyntax-only pretend that this
+            function has been written out so that we don't try to
+            expand it again.  */
+         if (flag_syntax_only)
+           TREE_ASM_WRITTEN (decl) = 1;
+         reconsider = 1;
+       }
+     }
+   return reconsider;
+ }
+
+ /* If we might be able to omit this function,
+    defer generation of RTL until end of input, and return nonzero.
+    Else, generate RTL and return zero (normal case).
+    Useful side-effect: deferring a function makes it possible
+    to inline forward-referenced calls.  */
+ int
+ maybe_defer_fn (fn)
+      tree fn;
+ {
+   /* 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 funtion exists.  */
+       (*debug_hooks->deferred_inline_function) (fn);
+       return 1;
+     }
+   return 0;
   }
Index: gcc/gcc/tree-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.h,v
retrieving revision 1.3
diff -c -d -r1.3 tree-inline.h
*** tree-inline.h       2001/10/08 20:54:07     1.3
--- tree-inline.h       2001/10/30 18:51:50
***************
*** 22,27 ****
--- 22,29 ----
   #ifndef GCC_TREE_INLINE_H
   #define GCC_TREE_INLINE_H

+ #include "varray.h"
+
   /* Function prototypes.  */

   void optimize_inline_calls PARAMS ((tree));
***************
*** 38,42 ****
--- 40,49 ----
      candidates.  */

   extern int flag_inline_trees;
+ extern varray_type deferred_fns;
+ #define deferred_fns_used \
+   (deferred_fns ? deferred_fns->elements_used : 0)
+ extern int flush_deferred_fns PARAMS ((void));
+ extern int maybe_defer_fn PARAMS ((tree fn));

   #endif /* GCC_TREE_INLINE_H */
Index: gcc/gcc/tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.276
diff -c -d -r1.276 tree.h
*** tree.h      2001/10/23 18:51:13     1.276
--- tree.h      2001/10/30 18:51:51
***************
*** 1691,1696 ****
--- 1691,1723 ----
      argument's depth.  */
   #define DECL_POINTER_DEPTH(DECL) (DECL_CHECK 
(DECL)->decl.pointer_depth)

+ /* True if codegen of this function is deferred and pushed onto the 
deferred_fn list.
+    See tree-inline.c .  */
+ #define DECL_DEFERRED_FN(DECL) \
+   (DECL_CHECK (DECL)->decl.deferred)
+
+ /* DECL_EXTERNAL must be set on a decl until the decl is actually 
emitted,
+    so that assemble_external will work properly.  So we have this flag 
to
+    tell us whether the decl is really not external.  */
+ #define DECL_NOT_REALLY_EXTERN(NODE) \
+   (DECL_CHECK (NODE)->decl.not_really_extern)
+
+ #define DECL_REALLY_EXTERN(NODE) \
+   (DECL_EXTERNAL (NODE) && ! DECL_NOT_REALLY_EXTERN (NODE))
+
+ /* DECL_NEEDED_P holds of a declaration when we need to emit its
+    definition.  This is true when the back-end tells us that
+    the symbol has been referenced in the generated code.  If, however,
+    we are not generating code, then it is also true when a symbol has
+    just been used somewhere, even if it's not really needed.  We need
+    anything that isn't comdat, but we don't know for sure whether or
+    not something is comdat until end-of-file.  */
+ #define DECL_NEEDED_P(DECL)                                           \
+   ((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))))
+
   struct function;

   struct tree_decl
***************
*** 1733,1739 ****
     unsigned non_addressable : 1;
     unsigned user_align : 1;
     unsigned uninlinable : 1;
!   /* Two unused bits.  */

     unsigned lang_flag_0 : 1;
     unsigned lang_flag_1 : 1;
--- 1760,1769 ----
     unsigned non_addressable : 1;
     unsigned user_align : 1;
     unsigned uninlinable : 1;
!   unsigned deferred : 1;
!   unsigned not_really_extern : 1;
!
!   /* Zero unused bits.  */

     unsigned lang_flag_0 : 1;
     unsigned lang_flag_1 : 1;
Index: gcc/gcc/cp/cp-lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-lang.c,v
retrieving revision 1.3
diff -c -d -r1.3 cp-lang.c
*** cp-lang.c   2001/10/25 17:57:03     1.3
--- cp-lang.c   2001/10/30 18:51:51
***************
*** 63,68 ****
--- 63,70 ----
     cp_copy_res_decl_for_inlining
   #undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P
   #define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P anon_aggr_type_p
+ #undef LANG_HOOKS_TREE_INLINING_EXPAND_BODY
+ #define LANG_HOOKS_TREE_INLINING_EXPAND_BODY expand_body

   /* Each front end provides its own hooks, for toplev.c.  */
   struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: gcc/gcc/cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.652
diff -c -d -r1.652 cp-tree.h
*** cp-tree.h   2001/10/23 09:14:11     1.652
--- cp-tree.h   2001/10/30 18:51:52
***************
*** 1708,1726 ****
     unsigned has_in_charge_parm_p : 1;
     unsigned has_vtt_parm_p : 1;

-   unsigned deferred : 1;
     unsigned use_template : 2;
     unsigned nonconverting : 1;
-   unsigned not_really_extern : 1;
     unsigned needs_final_overrider : 1;
     unsigned initialized_in_class : 1;
     unsigned pending_inline_p : 1;
-
     unsigned global_ctor_p : 1;
     unsigned global_dtor_p : 1;
     unsigned assignment_operator_p : 1;
     unsigned anticipated_p : 1;
!   /* Four unused bits.  */

     union {
       /* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
--- 1708,1724 ----
     unsigned has_in_charge_parm_p : 1;
     unsigned has_vtt_parm_p : 1;

     unsigned use_template : 2;
     unsigned nonconverting : 1;
     unsigned needs_final_overrider : 1;
     unsigned initialized_in_class : 1;
     unsigned pending_inline_p : 1;
     unsigned global_ctor_p : 1;
     unsigned global_dtor_p : 1;
+
     unsigned assignment_operator_p : 1;
     unsigned anticipated_p : 1;
!   /* Six unused bits.  */

     union {
       /* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
***************
*** 1779,1797 ****

   #define DEFARG_POINTER(NODE) 
(DEFAULT_ARG_CHECK(NODE)->identifier.id.str)

- /* DECL_NEEDED_P holds of a declaration when we need to emit its
-    definition.  This is true when the back-end tells us that
-    the symbol has been referenced in the generated code.  If, however,
-    we are not generating code, then it is also true when a symbol has
-    just been used somewhere, even if it's not really needed.  We need
-    anything that isn't comdat, but we don't know for sure whether or
-    not something is comdat until end-of-file.  */
- #define DECL_NEEDED_P(DECL)                                           \
-   ((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))))
-
   /* Non-zero iff DECL is memory-based.  The DECL_RTL of
      certain const variables might be a CONST_INT, or a REG
      in some cases.  We cannot use `memory_operand' as a test
--- 1777,1782 ----
***************
*** 2134,2143 ****
   #define DECL_SORTED_FIELDS(NODE) \
         (DECL_LANG_SPECIFIC (TYPE_DECL_CHECK (NODE))->u.sorted_fields)

- /* True if on the deferred_fns (see decl2.c) list.  */
- #define DECL_DEFERRED_FN(DECL) \
-   (DECL_LANG_SPECIFIC(DECL)->decl_flags.deferred)
-
   /* For a VAR_DECL, FUNCTION_DECL, TYPE_DECL or TEMPLATE_DECL:
      template-specific information.  */
   #define DECL_TEMPLATE_INFO(NODE) \
--- 2119,2124 ----
***************
*** 2846,2860 ****
      controlled by DECL_INLINE.  */
   #define DECL_DECLARED_INLINE_P(NODE) \
     (DECL_LANG_SPECIFIC (NODE)->decl_flags.base.declared_inline)
-
- /* DECL_EXTERNAL must be set on a decl until the decl is actually 
emitted,
-    so that assemble_external will work properly.  So we have this flag 
to
-    tell us whether the decl is really not external.  */
- #define DECL_NOT_REALLY_EXTERN(NODE) \
-   (DECL_LANG_SPECIFIC (NODE)->decl_flags.not_really_extern)
-
- #define DECL_REALLY_EXTERN(NODE) \
-   (DECL_EXTERNAL (NODE) && ! DECL_NOT_REALLY_EXTERN (NODE))

   /* A thunk is a stub function.

--- 2827,2832 ----
Index: gcc/gcc/cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.499
diff -c -d -r1.499 decl2.c
*** decl2.c     2001/10/28 19:24:59     1.499
--- decl2.c     2001/10/30 18:51:53
***************
*** 44,49 ****
--- 44,50 ----
   #include "timevar.h"
   #include "cpplib.h"
   #include "target.h"
+ #include "tree-inline.h"
   extern cpp_reader *parse_in;

   /* This structure contains information about the initializations
***************
*** 98,117 ****
   #define pending_statics_used \
     (pending_statics ? pending_statics->elements_used : 0)

- /* A list of functions which were declared inline, but which we
-    may need to emit outline anyway.  */
- static varray_type deferred_fns;
- #define deferred_fns_used \
-   (deferred_fns ? deferred_fns->elements_used : 0)
-
   /* Flag used when debugging spew.c */

   extern int spew_debug;

- /* Nonzero if we're done parsing and into end-of-file activities.  */
-
- int at_eof;
-
   /* Functions called along with real static constructors and 
destructors.  */

   tree static_ctors;
--- 99,108 ----
***************
*** 1879,1899 ****
     return t;
   }


- /* Defer the compilation of the FN until the end of compilation.  */
-
- void
- defer_fn (fn)
-      tree fn;
- {
-   if (DECL_DEFERRED_FN (fn))
-     return;
-   DECL_DEFERRED_FN (fn) = 1;
-   if (!deferred_fns)
-     VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
-
-   VARRAY_PUSH_TREE (deferred_fns, fn);
- }
-
   /* Hunts through the global anonymous union ANON_DECL, building
      appropriate VAR_DECLs.  Stores cleanups on the list of ELEMS, and
      returns a VAR_DECL whose size is the same as the size of the
--- 1870,1875 ----
***************
*** 3481,3529 ****
             }
         }

!       /* We lie to the back-end, pretending that some functions are
!        not defined when they really are.  This keeps these functions
!        from being put out unnecessarily.  But, we must stop lying
!        when the functions are referenced, or if they are not comdat
!        since they need to be put out now.  */
!       for (i = 0; i < deferred_fns_used; ++i)
!       {
!         tree decl = VARRAY_TREE (deferred_fns, i);
!
!         if (DECL_NOT_REALLY_EXTERN (decl)
!             && DECL_INITIAL (decl)
!             && DECL_NEEDED_P (decl))
!           DECL_EXTERNAL (decl) = 0;
!
!         /* If we're going to need to write this function out, and
!            there's already a body for it, create RTL for it now.
!            (There might be no body if this is a method we haven't
!            gotten around to synthesizing yet.)  */
!         if (!DECL_EXTERNAL (decl)
!             && DECL_NEEDED_P (decl)
!             && DECL_SAVED_TREE (decl)
!             && !TREE_ASM_WRITTEN (decl))
!           {
!             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);
!             /* 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;
!             /* If we're compiling -fsyntax-only pretend that this
!                function has been written out so that we don't try to
!                expand it again.  */
!             if (flag_syntax_only)
!               TREE_ASM_WRITTEN (decl) = 1;
!             reconsider = 1;
!           }
!       }

         if (deferred_fns_used
           && wrapup_global_declarations (&VARRAY_TREE (deferred_fns, 0),
--- 3457,3464 ----
             }
         }

!       if (flush_deferred_fns())
!       reconsider = 1;

         if (deferred_fns_used
           && wrapup_global_declarations (&VARRAY_TREE (deferred_fns, 0),
Index: gcc/gcc/cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.227
diff -c -d -r1.227 semantics.c
*** semantics.c 2001/10/28 19:25:00     1.227
--- semantics.c 2001/10/30 18:51:53
***************
*** 2442,2468 ****
     /* 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 funtion exists.  */
!       (*debug_hooks->deferred_inline_function) (fn);
!       return;
!     }

     /* Compute the appropriate object-file linkage for inline
        functions.  */
--- 2442,2449 ----
     /* 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 (maybe_defer_fn (fn))
!     return;

     /* Compute the appropriate object-file linkage for inline
        functions.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]