* 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
+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
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 \
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
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;
#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
((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
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, ...);
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,
static void
end_cleanup_fn (void)
{
- expand_body (finish_function (0));
+ expand_or_defer_fn (finish_function (0));
pop_from_top_level ();
}
#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
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");
/* 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));
/* 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
{
/* 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
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
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. */
}
}
- 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;
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);
/* Re-enable access control. */
pop_deferring_access_checks ();
- expand_body (finish_function (0));
+ expand_or_defer_fn (finish_function (0));
}
pop_from_top_level ();
}
finish_function_body (stmt);
- expand_body (finish_function (0));
+ expand_or_defer_fn (finish_function (0));
extract_interface_info ();
if (! context)
/* 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 ();
}
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;
/* Finish the function. */
d = finish_function (0);
- expand_body (d);
+ expand_or_defer_fn (d);
}
/* We're not deferring instantiation any more. */
#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
{
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. */
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. */