This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] Enable inline of forward-referenced fns in C
- To: gcc-patches at gcc dot gnu dot org
- Subject: [patch] Enable inline of forward-referenced fns in C
- From: stuart at apple dot com
- Date: Tue, 30 Oct 2001 11:02:46 -0800
- Cc: aoliva at redhat dot com
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. */