/* Top level of GNU C compiler
- Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
#include "insn-attr.h"
#include "insn-codes.h"
#include "insn-config.h"
+#include "hard-reg-set.h"
#include "recog.h"
#include "defaults.h"
#include "output.h"
#include "intl.h"
#include "ggc.h"
#include "graph.h"
+#include "loop.h"
+#include "regs.h"
+#include "timevar.h"
+
+#ifndef ACCUMULATE_OUTGOING_ARGS
+#define ACCUMULATE_OUTGOING_ARGS 0
+#endif
#ifdef DWARF_DEBUGGING_INFO
#include "dwarfout.h"
#define PREFERRED_DEBUGGING_TYPE NO_DEBUG
#endif
-#ifndef DIR_SEPARATOR
-#define DIR_SEPARATOR '/'
-#endif
-
-#if ! (defined (VMS) || defined (OS2))
+#if defined (HAVE_DECL_ENVIRON) && !HAVE_DECL_ENVIRON
extern char **environ;
#endif
-extern char *version_string;
/* Carry information from ASM_DECLARE_OBJECT_NAME
to ASM_FINISH_DECLARE_OBJECT. */
extern int size_directive_output;
extern tree last_assemble_variable_decl;
-static void notice PVPROTO((const char *s, ...)) ATTRIBUTE_PRINTF_1;
-static void set_target_switch PROTO((const char *));
-static const char *decl_name PROTO((tree, int));
-static void vmessage PROTO((const char *, const char *, va_list));
-static void v_message_with_file_and_line PROTO((const char *, int, int,
- const char *, va_list));
-static void v_message_with_decl PROTO((tree, int, const char *, va_list));
-static void file_and_line_for_asm PROTO((rtx, char **, int *));
-static void v_error_with_file_and_line PROTO((const char *, int,
- const char *, va_list));
-static void v_error_with_decl PROTO((tree, const char *, va_list));
-static void v_error_for_asm PROTO((rtx, const char *, va_list));
-static void verror PROTO((const char *, va_list));
-static void vfatal PROTO((const char *, va_list)) ATTRIBUTE_NORETURN;
-static void v_warning_with_file_and_line PROTO ((const char *, int,
- const char *, va_list));
-static void v_warning_with_decl PROTO((tree, const char *, va_list));
-static void v_warning_for_asm PROTO((rtx, const char *, va_list));
-static void vwarning PROTO((const char *, va_list));
-static void vpedwarn PROTO((const char *, va_list));
-static void v_pedwarn_with_decl PROTO((tree, const char *, va_list));
-static void v_pedwarn_with_file_and_line PROTO((const char *, int,
- const char *, va_list));
-static void vsorry PROTO((const char *, va_list));
-extern void set_fatal_function PROTO((void (*)(const char *, va_list)));
-static void float_signal PROTO((int)) ATTRIBUTE_NORETURN;
-static void pipe_closed PROTO((int)) ATTRIBUTE_NORETURN;
+static void set_target_switch PARAMS ((const char *));
+static const char *decl_name PARAMS ((tree, int));
+
+static void float_signal PARAMS ((int)) ATTRIBUTE_NORETURN;
+static void pipe_closed PARAMS ((int)) ATTRIBUTE_NORETURN;
#ifdef ASM_IDENTIFY_LANGUAGE
/* This might or might not be used in ASM_IDENTIFY_LANGUAGE. */
-static void output_lang_identify PROTO((FILE *)) ATTRIBUTE_UNUSED;
+static void output_lang_identify PARAMS ((FILE *)) ATTRIBUTE_UNUSED;
#endif
-static void open_dump_file PROTO((const char *, const char *));
-static void close_dump_file PROTO((void (*) (FILE *, rtx), rtx));
-static void dump_rtl PROTO((const char *, tree, void (*) (FILE *, rtx), rtx));
-static void clean_dump_file PROTO((const char *));
-static void compile_file PROTO((char *));
-static void display_help PROTO ((void));
-static void report_file_and_line PROTO ((const char *, int, int));
-static void vnotice PROTO ((FILE *, const char *, va_list));
-static void mark_file_stack PROTO ((void *));
-
-static void decode_d_option PROTO ((const char *));
-static int decode_f_option PROTO ((const char *));
-static int decode_W_option PROTO ((const char *));
-static int decode_g_option PROTO ((const char *));
-static unsigned independent_decode_option PROTO ((int, char **, unsigned));
-
-static void print_version PROTO((FILE *, const char *));
-static int print_single_switch PROTO((FILE *, int, int, const char *,
+static void compile_file PARAMS ((const char *));
+static void display_help PARAMS ((void));
+static void mark_file_stack PARAMS ((void *));
+
+static void decode_d_option PARAMS ((const char *));
+static int decode_f_option PARAMS ((const char *));
+static int decode_W_option PARAMS ((const char *));
+static int decode_g_option PARAMS ((const char *));
+static unsigned int independent_decode_option PARAMS ((int, char **,
+ unsigned int));
+
+static void print_version PARAMS ((FILE *, const char *));
+static int print_single_switch PARAMS ((FILE *, int, int, const char *,
const char *, const char *,
const char *, const char *));
-static void print_switch_values PROTO((FILE *, int, int, const char *,
+static void print_switch_values PARAMS ((FILE *, int, int, const char *,
const char *, const char *));
/* Length of line when printing switch values. */
/* Name of current original source file (what was input to cpp).
This comes from each #-command in the actual input. */
-char *input_filename;
+const char *input_filename;
/* Name of top-level original source file (what was input to cpp).
This comes from the #-command at the beginning of the actual input.
If there isn't any there, then this is the cc1 input file name. */
-char *main_input_filename;
+const char *main_input_filename;
/* Current line number in real source file. */
extern int target_flags;
-/* Flags saying which kinds of debugging dump have been requested. */
-
-int rtl_dump = 0;
-int rtl_dump_and_exit = 0;
-int jump_opt_dump = 0;
-int addressof_dump = 0;
-int cse_dump = 0;
-int gcse_dump = 0;
-int loop_dump = 0;
-int cse2_dump = 0;
-int branch_prob_dump = 0;
-int flow_dump = 0;
-int combine_dump = 0;
-int regmove_dump = 0;
-int sched_dump = 0;
-int local_reg_dump = 0;
-int global_reg_dump = 0;
-int flow2_dump = 0;
-int peephole2_dump = 0;
-int sched2_dump = 0;
-int jump2_opt_dump = 0;
-#ifdef DELAY_SLOTS
-int dbr_sched_dump = 0;
-#endif
-int flag_print_asm_name = 0;
-#ifdef STACK_REGS
-int stack_reg_dump = 0;
-#endif
-#ifdef MACHINE_DEPENDENT_REORG
-int mach_dep_reorg_dump = 0;
-#endif
-static int flag_print_mem = 0;
-static int version_flag = 0;
-static char * filename = 0;
+/* Describes a dump file. */
+
+struct dump_file_info
+{
+ /* The unique extension to apply, e.g. ".jump". */
+ const char * const extension;
+
+ /* The -d<c> character that enables this dump file. */
+ char const debug_switch;
+
+ /* True if there is a corresponding graph dump file. */
+ char const graph_dump_p;
+
+ /* True if the user selected this dump. */
+ char enabled;
+
+ /* True if the files have been initialized (ie truncated). */
+ char initialized;
+};
+
+/* Enumerate the extant dump files. */
+
+enum dump_file_index
+{
+ DFI_rtl,
+ DFI_sibling,
+ DFI_jump,
+ DFI_cse,
+ DFI_addressof,
+ DFI_ssa,
+ DFI_ussa,
+ DFI_gcse,
+ DFI_loop,
+ DFI_cse2,
+ DFI_cfg,
+ DFI_bp,
+ DFI_life,
+ DFI_combine,
+ DFI_ce,
+ DFI_regmove,
+ DFI_sched,
+ DFI_lreg,
+ DFI_greg,
+ DFI_flow2,
+ DFI_ce2,
+ DFI_peephole2,
+ DFI_rnreg,
+ DFI_sched2,
+ DFI_bbro,
+ DFI_jump2,
+ DFI_mach,
+ DFI_dbr,
+ DFI_stack,
+ DFI_MAX
+};
+
+/* Describes all the dump files. Should be kept in order of the
+ pass and in sync with dump_file_index above.
+
+ Remaining -d letters:
+
+ " h o q u "
+ " H K OPQ TUVWXYZ"
+*/
+
+struct dump_file_info dump_file[DFI_MAX] =
+{
+ { "rtl", 'r', 0, 0, 0 },
+ { "sibling", 'i', 0, 0, 0 },
+ { "jump", 'j', 0, 0, 0 },
+ { "cse", 's', 0, 0, 0 },
+ { "addressof", 'F', 0, 0, 0 },
+ { "ssa", 'e', 1, 0, 0 },
+ { "ussa", 'e', 1, 0, 0 }, /* Yes, duplicate enable switch. */
+ { "gcse", 'G', 1, 0, 0 },
+ { "loop", 'L', 1, 0, 0 },
+ { "cse2", 't', 1, 0, 0 },
+ { "cfg", 'f', 1, 0, 0 },
+ { "bp", 'b', 1, 0, 0 },
+ { "life", 'f', 1, 0, 0 }, /* Yes, duplicate enable switch. */
+ { "combine", 'c', 1, 0, 0 },
+ { "ce", 'C', 1, 0, 0 },
+ { "regmove", 'N', 1, 0, 0 },
+ { "sched", 'S', 1, 0, 0 },
+ { "lreg", 'l', 1, 0, 0 },
+ { "greg", 'g', 1, 0, 0 },
+ { "flow2", 'w', 1, 0, 0 },
+ { "ce2", 'E', 1, 0, 0 },
+ { "peephole2", 'z', 1, 0, 0 },
+ { "rnreg", 'n', 1, 0, 0 },
+ { "sched2", 'R', 1, 0, 0 },
+ { "bbro", 'B', 1, 0, 0 },
+ { "jump2", 'J', 1, 0, 0 },
+ { "mach", 'M', 1, 0, 0 },
+ { "dbr", 'd', 0, 0, 0 },
+ { "stack", 'k', 1, 0, 0 },
+};
+
+static int open_dump_file PARAMS ((enum dump_file_index, tree));
+static void close_dump_file PARAMS ((enum dump_file_index,
+ void (*) (FILE *, rtx), rtx));
+
+/* Other flags saying which kinds of debugging dump have been requested. */
+
+int rtl_dump_and_exit;
+int flag_print_asm_name;
+static int flag_print_mem;
+static int version_flag;
+static char * filename;
enum graph_dump_types graph_dump_format;
/* Name for output file of assembly code, specified with -o. */
int warningcount = 0;
int sorrycount = 0;
+/* The FUNCTION_DECL for the function currently being compiled,
+ or 0 if between functions. */
+tree current_function_decl;
+
+/* Set to the FUNC_BEGIN label of the current function, or NULL_TREE
+ if none. */
+tree current_function_func_begin_label;
+
/* Pointer to function to compute the name to use to print a declaration.
DECL is the declaration in question.
VERBOSITY determines what information will be printed:
2: and any other information that might be interesting, such as function
parameter types in C++. */
-const char *(*decl_printable_name) PROTO ((tree, int));
+const char *(*decl_printable_name) PARAMS ((tree, int));
/* Pointer to function to compute rtl for a language-specific tree code. */
typedef rtx (*lang_expand_expr_t)
- PROTO ((union tree_node *, rtx, enum machine_mode,
+ PARAMS ((union tree_node *, rtx, enum machine_mode,
enum expand_modifier modifier));
lang_expand_expr_t lang_expand_expr = 0;
-tree (*lang_expand_constant) PROTO((tree)) = 0;
+tree (*lang_expand_constant) PARAMS ((tree)) = 0;
/* Pointer to function to finish handling an incomplete decl at the
end of compilation. */
-void (*incomplete_decl_finalize_hook) PROTO((tree)) = 0;
+void (*incomplete_decl_finalize_hook) PARAMS ((tree)) = 0;
/* Nonzero if generating code to do profiling. */
int flag_branch_probabilities = 0;
+/* Nonzero if basic blocks should be reordered. */
+
+int flag_reorder_blocks = 0;
+
+/* Nonzero if registers should be renamed */
+
+int flag_rename_registers = 0;
+
/* Nonzero for -pedantic switch: warn about anything
that standard spec forbids. */
int in_system_header = 0;
-/* Nonzero means do stupid register allocation.
- Currently, this is 1 if `optimize' is 0. */
-
-int obey_regdecls = 0;
-
/* Don't print functions as they are compiled and don't print
times taken by the various passes. -quiet. */
int flag_fast_math = 0;
+/* Nonzero allows GCC to optimize sibling and tail recursive calls. */
+
+int flag_optimize_sibling_calls = 0;
+
/* Nonzero means the front end generally wants `errno' maintained by math
operations, like built-in SQRT, unless overridden by flag_fast_math. */
int flag_gnu_linker = 1;
#endif
+/* Enable SSA. */
+int flag_ssa = 0;
+
/* Tag all structures with __attribute__(packed) */
int flag_pack_struct = 0;
to be allocated dynamically. */
int flag_stack_check;
+/* When non-NULL, indicates that whenever space is allocated on the
+ stack, the resulting stack pointer must not pass this
+ address---that is, for stacks that grow downward, the stack pointer
+ must always be greater than or equal to this address; for stacks
+ that grow upward, the stack pointer must be less than this address.
+ At present, the rtx may be either a REG or a SYMBOL_REF, although
+ the support provided depends on the backend. */
+rtx stack_limit_rtx;
+
/* -fcheck-memory-usage causes extra code to be generated in order to check
memory accesses. This is used by a detector of bad memory accesses such
as Checker. */
For CHILL: defaults to off. */
int flag_bounds_check = 0;
+/* If one, renumber instruction UIDs to reduce the number of
+ unused UIDs if there are a lot of instructions. If greater than
+ one, unconditionally renumber instruction UIDs. */
+int flag_renumber_insns = 1;
+
/* Values of the -falign-* flags: how much to align labels in code.
0 means `use default', 1 means `don't align'.
For each variable, there is an _log variant which is the power
"Defer popping functions args from stack until later" },
{"omit-frame-pointer", &flag_omit_frame_pointer, 1,
"When possible do not generate stack frames"},
+ {"optimize-sibling-calls", &flag_optimize_sibling_calls, 1,
+ "Optimize sibling and tail recursive calls" },
{"cse-follow-jumps", &flag_cse_follow_jumps, 1,
"When running CSE, follow jumps to their targets" },
{"cse-skip-blocks", &flag_cse_skip_blocks, 1,
"Create data files needed by gcov" },
{"branch-probabilities", &flag_branch_probabilities, 1,
"Use profiling information for branch probabilities" },
+ {"reorder-blocks", &flag_reorder_blocks, 1,
+ "Reorder basic blocks to improve code placement" },
+ {"rename-registers", &flag_rename_registers, 1,
+ "Do the register renaming optimization pass"},
{"fast-math", &flag_fast_math, 1,
"Improve FP speed by violating ANSI & IEEE rules" },
{"common", &flag_no_common, 0,
"Suppress output of instruction numbers and line number notes in debugging dumps"},
{"instrument-functions", &flag_instrument_function_entry_exit, 1,
"Instrument function entry/exit with profiling calls"},
+ {"ssa", &flag_ssa, 1,
+ "Enable SSA optimizations" },
{"leading-underscore", &flag_leading_underscore, 1,
"External symbols have a leading underscore" },
{"ident", &flag_no_ident, 0,
{ "-Wno-sign-compare", "" },
{ "-Wfloat-equal", "Warn about testing equality of floating point numbers" },
{ "-Wno-float-equal", "" },
- { "-Wunknown-pragmas", "Warn about unrecognised pragmas" },
+ { "-Wunknown-pragmas", "Warn about unrecognized pragmas" },
{ "-Wno-unknown-pragmas", "" },
{ "-Wstrict-prototypes", "Warn about non-prototyped function decls" },
{ "-Wno-strict-prototypes", "" },
int warnings_are_errors = 0;
-/* Nonzero to warn about unused local variables. */
+/* Nonzero to warn about unused variables, functions et.al. */
-int warn_unused;
+int warn_unused_function;
+int warn_unused_label;
+int warn_unused_parameter;
+int warn_unused_variable;
+int warn_unused_value;
+
+void
+set_Wunused (setting)
+ int setting;
+{
+ warn_unused_function = setting;
+ warn_unused_label = setting;
+ /* Unused function parameter warnings are reported when either ``-W
+ -Wunused'' or ``-Wunused-parameter'' is specified. Differentiate
+ -Wunused by setting WARN_UNUSED_PARAMETER to -1 */
+ if (!setting)
+ warn_unused_parameter = 0;
+ else if (!warn_unused_parameter)
+ warn_unused_parameter = -1;
+ warn_unused_variable = setting;
+ warn_unused_value = setting;
+}
/* Nonzero to warn about code which is never reached. */
characters. The value N is in `id_clash_len'. */
int warn_id_clash;
-unsigned id_clash_len;
+int id_clash_len;
/* Nonzero means warn about any objects definitions whose size is larger
than N bytes. Also want about function definitions whose returned
values are larger than N bytes. The value N is in `larger_than_size'. */
int warn_larger_than;
-unsigned larger_than_size;
+HOST_WIDE_INT larger_than_size;
/* Nonzero means warn if inline function is too large. */
int warn_aggregate_return;
+/* Warn if packed attribute on struct is unnecessary and inefficient. */
+
+int warn_packed;
+
+/* Warn when gcc pads a structure to an alignment boundary. */
+
+int warn_padded;
+
/* Likewise for -W. */
lang_independent_options W_options[] =
{
- {"unused", &warn_unused, 1, "Warn when a variable is unused" },
+ {"unused-function", &warn_unused_function, 1, "Warn when a function is unused" },
+ {"unused-label", &warn_unused_label, 1, "Warn when a label is unused" },
+ {"unused-parameter", &warn_unused_parameter, 1, "Warn when a function parameter is unused" },
+ {"unused-variable", &warn_unused_variable, 1, "Warn when a variable is unused" },
+ {"unused-value", &warn_unused_value, 1, "Warn when an expression value is unused" },
{"error", &warnings_are_errors, 1, ""},
{"shadow", &warn_shadow, 1, "Warn when one local variable shadows another" },
{"switch", &warn_switch, 1,
{"uninitialized", &warn_uninitialized, 1,
"Warn about unitialized automatic variables"},
{"inline", &warn_inline, 1,
- "Warn when an inlined function cannot be inlined"}
+ "Warn when an inlined function cannot be inlined"},
+ {"packed", &warn_packed, 1,
+ "Warn when the packed attribute has no effect on struct layout"},
+ {"padded", &warn_padded, 1,
+ "Warn when padding is required to align struct members"}
};
\f
/* Output files for assembler code (real compiler output)
return atoi (p);
}
-
-/* Time accumulators, to count the total time spent in various passes. */
-
-int parse_time;
-int varconst_time;
-int integration_time;
-int jump_time;
-int cse_time;
-int gcse_time;
-int loop_time;
-int cse2_time;
-int branch_prob_time;
-int flow_time;
-int combine_time;
-int regmove_time;
-int sched_time;
-int local_alloc_time;
-int global_alloc_time;
-int flow2_time;
-int peephole2_time;
-int sched2_time;
-int dbr_sched_time;
-int shorten_branch_time;
-int stack_reg_time;
-int final_time;
-int symout_time;
-int dump_time;
-int gc_time;
-int all_time;
\f
-/* Return time used so far, in microseconds. */
-
-long
-get_run_time ()
-{
- if (quiet_flag)
- return 0;
-
-#ifdef __BEOS__
- return 0;
-#else /* not BeOS */
-#if defined (_WIN32) && !defined (__CYGWIN__)
- if (clock() < 0)
- return 0;
- else
- return (clock() * 1000);
-#else /* not _WIN32 */
-#ifdef _SC_CLK_TCK
- {
- static int tick;
- struct tms tms;
- if (tick == 0)
- tick = 1000000 / sysconf(_SC_CLK_TCK);
- times (&tms);
- return (tms.tms_utime + tms.tms_stime) * tick;
- }
-#else
-#ifdef USG
- {
- struct tms tms;
-# if HAVE_SYSCONF && defined _SC_CLK_TCK
-# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
-# else
-# ifdef CLK_TCK
-# define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
-# else
-# define TICKS_PER_SECOND HZ /* traditional UNIX */
-# endif
-# endif
- times (&tms);
- return (tms.tms_utime + tms.tms_stime) * (1000000 / TICKS_PER_SECOND);
- }
-#else
-#ifndef VMS
- {
- struct rusage rusage;
- getrusage (0, &rusage);
- return (rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec
- + rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec);
- }
-#else /* VMS */
- {
- struct
- {
- int proc_user_time;
- int proc_system_time;
- int child_user_time;
- int child_system_time;
- } vms_times;
- times ((void *) &vms_times);
- return (vms_times.proc_user_time + vms_times.proc_system_time) * 10000;
- }
-#endif /* VMS */
-#endif /* USG */
-#endif /* _SC_CLK_TCK */
-#endif /* _WIN32 */
-#endif /* __BEOS__ */
-}
-
-#define TIMEVAR(VAR, BODY) \
-do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0)
-
-void
-print_time (str, total)
- const char *str;
- int total;
-{
- fprintf (stderr,
- "time in %s: %d.%06d (%.0f%%)\n",
- str, total / 1000000, total % 1000000,
- (double)total / (double)all_time * 100.0);
-}
-
-/* Count an error or warning. Return 1 if the message should be printed. */
-
-int
-count_error (warningp)
- int warningp;
-{
- if (warningp && inhibit_warnings)
- return 0;
-
- if (warningp && !warnings_are_errors)
- warningcount++;
- else
- {
- static int warning_message = 0;
-
- if (warningp && !warning_message)
- {
- notice ("%s: warnings being treated as errors\n", progname);
- warning_message = 1;
- }
- errorcount++;
- }
-
- return 1;
-}
-
-/* Print a fatal error message. NAME is the text.
- Also include a system error message based on `errno'. */
-
-void
-pfatal_with_name (name)
- const char *name;
-{
- fprintf (stderr, "%s: ", progname);
- perror (name);
- exit (FATAL_EXIT_CODE);
-}
-
-void
-fatal_io_error (name)
- const char *name;
-{
- notice ("%s: %s: I/O error\n", progname, name);
- exit (FATAL_EXIT_CODE);
-}
-
/* This is the default decl_printable_name function. */
static const char *
}
\f
/* Mark P for GC. Also mark main_input_filename and input_filename. */
+
static void
mark_file_stack (p)
void *p;
stack = stack->next;
}
}
+\f
-static int need_error_newline;
-
-/* Function of last error message;
- more generally, function such that if next error message is in it
- then we don't have to mention the function name. */
-static tree last_error_function = NULL;
+/* This calls abort and is used to avoid problems when abort if a macro.
+ It is used when we need to pass the address of abort. */
-/* Used to detect when input_file_stack has changed since last described. */
-static int last_error_tick;
+void
+do_abort ()
+{
+ abort ();
+}
-/* Called when the start of a function definition is parsed,
- this function prints on stderr the name of the function. */
+/* When `malloc.c' is compiled with `rcheck' defined,
+ it calls this function to report clobberage. */
void
-announce_function (decl)
- tree decl;
+botch (s)
+ const char * s ATTRIBUTE_UNUSED;
{
- if (! quiet_flag)
- {
- if (rtl_dump_and_exit)
- fprintf (stderr, "%s ", IDENTIFIER_POINTER (DECL_NAME (decl)));
- else
- fprintf (stderr, " %s", (*decl_printable_name) (decl, 2));
- fflush (stderr);
- need_error_newline = 1;
- last_error_function = current_function_decl;
- }
+ abort ();
}
+\f
+/* Return the logarithm of X, base 2, considering X unsigned,
+ if X is a power of 2. Otherwise, returns -1.
-/* The default function to print out name of current function that caused
- an error. */
+ This should be used via the `exact_log2' macro. */
-void
-default_print_error_function (file)
- const char *file;
+int
+exact_log2_wide (x)
+ register unsigned HOST_WIDE_INT x;
{
- if (last_error_function != current_function_decl)
- {
- if (file)
- fprintf (stderr, "%s: ", file);
+ register int log = 0;
+ /* Test for 0 or a power of 2. */
+ if (x == 0 || x != (x & -x))
+ return -1;
+ while ((x >>= 1) != 0)
+ log++;
+ return log;
+}
- if (current_function_decl == NULL)
- notice ("At top level:\n");
- else
- notice ((TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE
- ? "In method `%s':\n"
- : "In function `%s':\n"),
- (*decl_printable_name) (current_function_decl, 2));
+/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
+ If X is 0, return -1.
- last_error_function = current_function_decl;
- }
+ This should be used via the floor_log2 macro. */
+
+int
+floor_log2_wide (x)
+ register unsigned HOST_WIDE_INT x;
+{
+ register int log = -1;
+ while (x != 0)
+ log++,
+ x >>= 1;
+ return log;
}
-/* Called by report_error_function to print out function name.
- * Default may be overridden by language front-ends. */
+static int float_handler_set;
+int float_handled;
+jmp_buf float_handler;
+
+/* Signals actually come here. */
-void (*print_error_function) PROTO((const char *)) =
- default_print_error_function;
+static void
+float_signal (signo)
+ /* If this is missing, some compilers complain. */
+ int signo ATTRIBUTE_UNUSED;
+{
+ if (float_handled == 0)
+ abort ();
+#if defined (USG) || defined (hpux)
+ signal (SIGFPE, float_signal); /* re-enable the signal catcher */
+#endif
+ float_handled = 0;
+ signal (SIGFPE, float_signal);
+ longjmp (float_handler, 1);
+}
-/* Prints out, if necessary, the name of the current function
- that caused an error. Called from all error and warning functions.
- We ignore the FILE parameter, as it cannot be relied upon. */
+/* Specify where to longjmp to when a floating arithmetic error happens.
+ If HANDLER is 0, it means don't handle the errors any more. */
void
-report_error_function (file)
- const char *file ATTRIBUTE_UNUSED;
+set_float_handler (handler)
+ jmp_buf handler;
{
- struct file_stack *p;
+ float_handled = (handler != 0);
+ if (handler)
+ bcopy ((char *) handler, (char *) float_handler, sizeof (float_handler));
- if (need_error_newline)
+ if (float_handled && ! float_handler_set)
{
- fprintf (stderr, "\n");
- need_error_newline = 0;
+ signal (SIGFPE, float_signal);
+ float_handler_set = 1;
}
+}
+
+/* This is a wrapper function for code which might elicit an
+ arithmetic exception. That code should be passed in as a function
+ pointer FN, and one argument DATA. DATA is usually a struct which
+ contains the real input and output for function FN. This function
+ returns 0 (failure) if longjmp was called (i.e. an exception
+ occured.) It returns 1 (success) otherwise. */
+
+int
+do_float_handler (fn, data)
+ void (*fn) PARAMS ((PTR));
+ PTR data;
+{
+ jmp_buf buf;
- if (input_file_stack && input_file_stack->next != 0
- && input_file_stack_tick != last_error_tick)
+ if (setjmp (buf))
{
- for (p = input_file_stack->next; p; p = p->next)
- notice ((p == input_file_stack->next
- ? "In file included from %s:%d"
- : ",\n from %s:%d"),
- p->name, p->line);
- fprintf (stderr, ":\n");
- last_error_tick = input_file_stack_tick;
+ /* We got here via longjmp() caused by an exception in function fn() */
+ set_float_handler (NULL);
+ return 0;
}
- (*print_error_function) (input_filename);
+ set_float_handler (buf);
+ (*fn)(data);
+ set_float_handler (NULL);
+ return 1;
}
-\f
-/* Print a message. */
-static void
-vnotice (file, msgid, ap)
- FILE *file;
- const char *msgid;
- va_list ap;
-{
- vfprintf (file, _(msgid), ap);
-}
+/* Specify, in HANDLER, where to longjmp to when a floating arithmetic
+ error happens, pushing the previous specification into OLD_HANDLER.
+ Return an indication of whether there was a previous handler in effect. */
-static void
-notice VPROTO((const char *msgid, ...))
+int
+push_float_handler (handler, old_handler)
+ jmp_buf handler, old_handler;
{
-#ifndef ANSI_PROTOTYPES
- char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
+ int was_handled = float_handled;
-#ifndef ANSI_PROTOTYPES
- msgid = va_arg (ap, char *);
-#endif
+ float_handled = 1;
+ if (was_handled)
+ memcpy ((char *) old_handler, (char *) float_handler,
+ sizeof (float_handler));
- vnotice (stderr, msgid, ap);
- va_end (ap);
+ memcpy ((char *) float_handler, (char *) handler, sizeof (float_handler));
+ return was_handled;
}
+/* Restore the previous specification of whether and where to longjmp to
+ when a floating arithmetic error happens. */
+
void
-fnotice VPROTO((FILE *file, const char *msgid, ...))
+pop_float_handler (handled, handler)
+ int handled;
+ jmp_buf handler;
{
-#ifndef ANSI_PROTOTYPES
- FILE *file;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- file = va_arg (ap, FILE *);
- msgid = va_arg (ap, const char *);
-#endif
-
- vnotice (file, msgid, ap);
- va_end (ap);
+ float_handled = handled;
+ if (handled)
+ bcopy ((char *) handler, (char *) float_handler, sizeof (float_handler));
}
-/* Report FILE and LINE (or program name), and optionally just WARN. */
+/* Handler for SIGPIPE. */
static void
-report_file_and_line (file, line, warn)
- const char *file;
- int line;
- int warn;
+pipe_closed (signo)
+ /* If this is missing, some compilers complain. */
+ int signo ATTRIBUTE_UNUSED;
{
- if (file)
- fprintf (stderr, "%s:%d: ", file, line);
- else
- fprintf (stderr, "%s: ", progname);
-
- if (warn)
- notice ("warning: ");
-}
-
-/* Print a message. */
-
-static void
-vmessage (prefix, msgid, ap)
- const char *prefix;
- const char *msgid;
- va_list ap;
-{
- if (prefix)
- fprintf (stderr, "%s: ", prefix);
-
- vfprintf (stderr, msgid, ap);
-}
-
-/* Print a message relevant to line LINE of file FILE. */
-
-static void
-v_message_with_file_and_line (file, line, warn, msgid, ap)
- const char *file;
- int line;
- int warn;
- const char *msgid;
- va_list ap;
-{
- report_file_and_line (file, line, warn);
- vnotice (stderr, msgid, ap);
- fputc ('\n', stderr);
-}
-
-/* Print a message relevant to the given DECL. */
-
-static void
-v_message_with_decl (decl, warn, msgid, ap)
- tree decl;
- int warn;
- const char *msgid;
- va_list ap;
-{
- const char *p;
-
- report_file_and_line (DECL_SOURCE_FILE (decl),
- DECL_SOURCE_LINE (decl), warn);
-
- /* Do magic to get around lack of varargs support for insertion
- of arguments into existing list. We know that the decl is first;
- we ass_u_me that it will be printed with "%s". */
-
- for (p = _(msgid); *p; ++p)
- {
- if (*p == '%')
- {
- if (*(p + 1) == '%')
- ++p;
- else if (*(p + 1) != 's')
- abort ();
- else
- break;
- }
- }
-
- if (p > _(msgid)) /* Print the left-hand substring. */
- {
- char fmt[sizeof "%.255s"];
- long width = p - _(msgid);
-
- if (width > 255L) width = 255L; /* arbitrary */
- sprintf (fmt, "%%.%lds", width);
- fprintf (stderr, fmt, _(msgid));
- }
-
- if (*p == '%') /* Print the name. */
- {
- const char *n = (DECL_NAME (decl)
- ? (*decl_printable_name) (decl, 2)
- : "((anonymous))");
- fputs (n, stderr);
- while (*p)
- {
- ++p;
- if (ISALPHA (*(p - 1) & 0xFF))
- break;
- }
- }
-
- if (*p) /* Print the rest of the message. */
- vmessage ((char *)NULL, p, ap);
-
- fputc ('\n', stderr);
-}
-
-/* Figure file and line of the given INSN. */
-
-static void
-file_and_line_for_asm (insn, pfile, pline)
- rtx insn;
- char **pfile;
- int *pline;
-{
- rtx body = PATTERN (insn);
- rtx asmop;
-
- /* Find the (or one of the) ASM_OPERANDS in the insn. */
- if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
- asmop = SET_SRC (body);
- else if (GET_CODE (body) == ASM_OPERANDS)
- asmop = body;
- else if (GET_CODE (body) == PARALLEL
- && GET_CODE (XVECEXP (body, 0, 0)) == SET)
- asmop = SET_SRC (XVECEXP (body, 0, 0));
- else if (GET_CODE (body) == PARALLEL
- && GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
- asmop = XVECEXP (body, 0, 0);
- else
- asmop = NULL;
-
- if (asmop)
- {
- *pfile = ASM_OPERANDS_SOURCE_FILE (asmop);
- *pline = ASM_OPERANDS_SOURCE_LINE (asmop);
- }
- else
- {
- *pfile = input_filename;
- *pline = lineno;
- }
-}
-
-/* Report an error at line LINE of file FILE. */
-
-static void
-v_error_with_file_and_line (file, line, msgid, ap)
- const char *file;
- int line;
- const char *msgid;
- va_list ap;
-{
- count_error (0);
- report_error_function (file);
- v_message_with_file_and_line (file, line, 0, msgid, ap);
-}
-
-void
-error_with_file_and_line VPROTO((const char *file, int line,
- const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- const char *file;
- int line;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- file = va_arg (ap, const char *);
- line = va_arg (ap, int);
- msgid = va_arg (ap, const char *);
-#endif
-
- v_error_with_file_and_line (file, line, msgid, ap);
- va_end (ap);
-}
-
-/* Report an error at the declaration DECL.
- MSGID is a format string which uses %s to substitute the declaration
- name; subsequent substitutions are a la printf. */
-
-static void
-v_error_with_decl (decl, msgid, ap)
- tree decl;
- const char *msgid;
- va_list ap;
-{
- count_error (0);
- report_error_function (DECL_SOURCE_FILE (decl));
- v_message_with_decl (decl, 0, msgid, ap);
-}
-
-void
-error_with_decl VPROTO((tree decl, const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- tree decl;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- decl = va_arg (ap, tree);
- msgid = va_arg (ap, const char *);
-#endif
-
- v_error_with_decl (decl, msgid, ap);
- va_end (ap);
-}
-
-/* Report an error at the line number of the insn INSN.
- This is used only when INSN is an `asm' with operands,
- and each ASM_OPERANDS records its own source file and line. */
-
-static void
-v_error_for_asm (insn, msgid, ap)
- rtx insn;
- const char *msgid;
- va_list ap;
-{
- char *file;
- int line;
-
- count_error (0);
- file_and_line_for_asm (insn, &file, &line);
- report_error_function (file);
- v_message_with_file_and_line (file, line, 0, msgid, ap);
-}
-
-void
-error_for_asm VPROTO((rtx insn, const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- rtx insn;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- insn = va_arg (ap, rtx);
- msgid = va_arg (ap, const char *);
-#endif
-
- v_error_for_asm (insn, msgid, ap);
- va_end (ap);
-}
-
-/* Report an error at the current line number. */
-
-static void
-verror (msgid, ap)
- const char *msgid;
- va_list ap;
-{
- v_error_with_file_and_line (input_filename, lineno, msgid, ap);
-}
-
-void
-error VPROTO((const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- msgid = va_arg (ap, const char *);
-#endif
-
- verror (msgid, ap);
- va_end (ap);
-}
-
-/* Report a fatal error at the current line number. Allow a front end to
- intercept the message. */
-
-static void (*fatal_function) PROTO ((const char *, va_list));
-
-/* Set the function to call when a fatal error occurs. */
-
-void
-set_fatal_function (f)
- void (*f) PROTO ((const char *, va_list));
-{
- fatal_function = f;
-}
-
-static void
-vfatal (msgid, ap)
- const char *msgid;
- va_list ap;
-{
- if (fatal_function != 0)
- (*fatal_function) (_(msgid), ap);
-
- verror (msgid, ap);
- exit (FATAL_EXIT_CODE);
-}
-
-void
-fatal VPROTO((const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- msgid = va_arg (ap, const char *);
-#endif
-
- vfatal (msgid, ap);
- va_end (ap);
-}
-
-void
-_fatal_insn (msgid, insn, file, line, function)
- const char *msgid;
- rtx insn;
- const char *file;
- int line;
- const char *function;
-{
- error (msgid);
- debug_rtx (insn);
- fancy_abort (file, line, function);
-}
-
-void
-_fatal_insn_not_found (insn, file, line, function)
- rtx insn;
- const char *file;
- int line;
- const char *function;
-{
- if (INSN_CODE (insn) < 0)
- _fatal_insn ("Unrecognizable insn:", insn, file, line, function);
- else
- _fatal_insn ("Insn does not satisfy its constraints:",
- insn, file, line, function);
-}
-
-/* Report a warning at line LINE of file FILE. */
-
-static void
-v_warning_with_file_and_line (file, line, msgid, ap)
- const char *file;
- int line;
- const char *msgid;
- va_list ap;
-{
- if (count_error (1))
- {
- report_error_function (file);
- v_message_with_file_and_line (file, line, 1, msgid, ap);
- }
-}
-
-void
-warning_with_file_and_line VPROTO((const char *file, int line,
- const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- const char *file;
- int line;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- file = va_arg (ap, const char *);
- line = va_arg (ap, int);
- msgid = va_arg (ap, const char *);
-#endif
-
- v_warning_with_file_and_line (file, line, msgid, ap);
- va_end (ap);
-}
-
-/* Report a warning at the declaration DECL.
- MSGID is a format string which uses %s to substitute the declaration
- name; subsequent substitutions are a la printf. */
-
-static void
-v_warning_with_decl (decl, msgid, ap)
- tree decl;
- const char *msgid;
- va_list ap;
-{
- if (count_error (1))
- {
- report_error_function (DECL_SOURCE_FILE (decl));
- v_message_with_decl (decl, 1, msgid, ap);
- }
-}
-
-void
-warning_with_decl VPROTO((tree decl, const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- tree decl;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- decl = va_arg (ap, tree);
- msgid = va_arg (ap, const char *);
-#endif
-
- v_warning_with_decl (decl, msgid, ap);
- va_end (ap);
-}
-
-/* Report a warning at the line number of the insn INSN.
- This is used only when INSN is an `asm' with operands,
- and each ASM_OPERANDS records its own source file and line. */
-
-static void
-v_warning_for_asm (insn, msgid, ap)
- rtx insn;
- const char *msgid;
- va_list ap;
-{
- if (count_error (1))
- {
- char *file;
- int line;
-
- file_and_line_for_asm (insn, &file, &line);
- report_error_function (file);
- v_message_with_file_and_line (file, line, 1, msgid, ap);
- }
-}
-
-void
-warning_for_asm VPROTO((rtx insn, const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- rtx insn;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- insn = va_arg (ap, rtx);
- msgid = va_arg (ap, const char *);
-#endif
-
- v_warning_for_asm (insn, msgid, ap);
- va_end (ap);
-}
-
-/* Report a warning at the current line number. */
-
-static void
-vwarning (msgid, ap)
- const char *msgid;
- va_list ap;
-{
- v_warning_with_file_and_line (input_filename, lineno, msgid, ap);
-}
-
-void
-warning VPROTO((const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- msgid = va_arg (ap, const char *);
-#endif
-
- vwarning (msgid, ap);
- va_end (ap);
-}
-
-/* These functions issue either warnings or errors depending on
- -pedantic-errors. */
-
-static void
-vpedwarn (msgid, ap)
- const char *msgid;
- va_list ap;
-{
- if (flag_pedantic_errors)
- verror (msgid, ap);
- else
- vwarning (msgid, ap);
-}
-
-void
-pedwarn VPROTO((const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- msgid = va_arg (ap, const char *);
-#endif
-
- vpedwarn (msgid, ap);
- va_end (ap);
-}
-
-static void
-v_pedwarn_with_decl (decl, msgid, ap)
- tree decl;
- const char *msgid;
- va_list ap;
-{
- /* We don't want -pedantic-errors to cause the compilation to fail from
- "errors" in system header files. Sometimes fixincludes can't fix what's
- broken (eg: unsigned char bitfields - fixing it may change the alignment
- which will cause programs to mysteriously fail because the C library
- or kernel uses the original layout). There's no point in issuing a
- warning either, it's just unnecessary noise. */
-
- if (! DECL_IN_SYSTEM_HEADER (decl))
- {
- if (flag_pedantic_errors)
- v_error_with_decl (decl, msgid, ap);
- else
- v_warning_with_decl (decl, msgid, ap);
- }
-}
-
-void
-pedwarn_with_decl VPROTO((tree decl, const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- tree decl;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- decl = va_arg (ap, tree);
- msgid = va_arg (ap, const char *);
-#endif
-
- v_pedwarn_with_decl (decl, msgid, ap);
- va_end (ap);
-}
-
-static void
-v_pedwarn_with_file_and_line (file, line, msgid, ap)
- const char *file;
- int line;
- const char *msgid;
- va_list ap;
-{
- if (flag_pedantic_errors)
- v_error_with_file_and_line (file, line, msgid, ap);
- else
- v_warning_with_file_and_line (file, line, msgid, ap);
-}
-
-void
-pedwarn_with_file_and_line VPROTO((const char *file, int line,
- const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- const char *file;
- int line;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- file = va_arg (ap, const char *);
- line = va_arg (ap, int);
- msgid = va_arg (ap, const char *);
-#endif
-
- v_pedwarn_with_file_and_line (file, line, msgid, ap);
- va_end (ap);
-}
-
-/* Apologize for not implementing some feature. */
-
-static void
-vsorry (msgid, ap)
- const char *msgid;
- va_list ap;
-{
- sorrycount++;
- if (input_filename)
- fprintf (stderr, "%s:%d: ", input_filename, lineno);
- else
- fprintf (stderr, "%s: ", progname);
- notice ("sorry, not implemented: ");
- vnotice (stderr, msgid, ap);
- fputc ('\n', stderr);
-}
-
-void
-sorry VPROTO((const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- msgid = va_arg (ap, const char *);
-#endif
-
- vsorry (msgid, ap);
- va_end (ap);
-}
-\f
-
-/* This calls abort and is used to avoid problems when abort if a macro.
- It is used when we need to pass the address of abort. */
-
-void
-do_abort ()
-{
- abort ();
-}
-
-/* When `malloc.c' is compiled with `rcheck' defined,
- it calls this function to report clobberage. */
-
-void
-botch (s)
- const char * s ATTRIBUTE_UNUSED;
-{
- abort ();
-}
-\f
-/* Return the logarithm of X, base 2, considering X unsigned,
- if X is a power of 2. Otherwise, returns -1.
-
- This should be used via the `exact_log2' macro. */
-
-int
-exact_log2_wide (x)
- register unsigned HOST_WIDE_INT x;
-{
- register int log = 0;
- /* Test for 0 or a power of 2. */
- if (x == 0 || x != (x & -x))
- return -1;
- while ((x >>= 1) != 0)
- log++;
- return log;
-}
-
-/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
- If X is 0, return -1.
-
- This should be used via the floor_log2 macro. */
-
-int
-floor_log2_wide (x)
- register unsigned HOST_WIDE_INT x;
-{
- register int log = -1;
- while (x != 0)
- log++,
- x >>= 1;
- return log;
-}
-
-static int float_handler_set;
-int float_handled;
-jmp_buf float_handler;
-
-/* Signals actually come here. */
-
-static void
-float_signal (signo)
- /* If this is missing, some compilers complain. */
- int signo ATTRIBUTE_UNUSED;
-{
- if (float_handled == 0)
- abort ();
-#if defined (USG) || defined (hpux)
- signal (SIGFPE, float_signal); /* re-enable the signal catcher */
-#endif
- float_handled = 0;
- signal (SIGFPE, float_signal);
- longjmp (float_handler, 1);
-}
-
-/* Specify where to longjmp to when a floating arithmetic error happens.
- If HANDLER is 0, it means don't handle the errors any more. */
-
-void
-set_float_handler (handler)
- jmp_buf handler;
-{
- float_handled = (handler != 0);
- if (handler)
- bcopy ((char *) handler, (char *) float_handler, sizeof (float_handler));
-
- if (float_handled && ! float_handler_set)
- {
- signal (SIGFPE, float_signal);
- float_handler_set = 1;
- }
-}
-
-/* This is a wrapper function for code which might elicit an
- arithmetic exception. That code should be passed in as a function
- pointer FN, and one argument DATA. DATA is usually a struct which
- contains the real input and output for function FN. This function
- returns 0 (failure) if longjmp was called (i.e. an exception
- occured.) It returns 1 (success) otherwise. */
-
-int
-do_float_handler (fn, data)
- void (*fn) PROTO ((PTR));
- PTR data;
-{
- jmp_buf buf;
-
- if (setjmp (buf))
- {
- /* We got here via longjmp() caused by an exception in function fn() */
- set_float_handler (NULL);
- return 0;
- }
-
- set_float_handler (buf);
- (*fn)(data);
- set_float_handler (NULL);
- return 1;
-}
-
-/* Specify, in HANDLER, where to longjmp to when a floating arithmetic
- error happens, pushing the previous specification into OLD_HANDLER.
- Return an indication of whether there was a previous handler in effect. */
-
-int
-push_float_handler (handler, old_handler)
- jmp_buf handler, old_handler;
-{
- int was_handled = float_handled;
-
- float_handled = 1;
- if (was_handled)
- memcpy ((char *) old_handler, (char *) float_handler,
- sizeof (float_handler));
-
- memcpy ((char *) float_handler, (char *) handler, sizeof (float_handler));
- return was_handled;
-}
-
-/* Restore the previous specification of whether and where to longjmp to
- when a floating arithmetic error happens. */
-
-void
-pop_float_handler (handled, handler)
- int handled;
- jmp_buf handler;
-{
- float_handled = handled;
- if (handled)
- bcopy ((char *) handler, (char *) float_handler, sizeof (float_handler));
-}
-
-/* Handler for SIGPIPE. */
-
-static void
-pipe_closed (signo)
- /* If this is missing, some compilers complain. */
- int signo ATTRIBUTE_UNUSED;
-{
- fatal ("output pipe has been closed");
+ fatal ("output pipe has been closed");
}
/* Strip off a legitimate source ending from the input string NAME of
/* NA gets INPUT_NAME sans directory names. */
while (na > input_name)
{
- if (na[-1] == '/')
- break;
-#ifdef DIR_SEPARATOR
- if (na[-1] == DIR_SEPARATOR)
- break;
-#endif
+ if (IS_DIR_SEPARATOR (na[-1]))
+ break;
na--;
}
}
#endif
-/* Routine to open a dump file. */
-static void
-open_dump_file (suffix, function_name)
- const char *suffix;
- const char *function_name;
+/* Routine to open a dump file. Return true if the dump file is enabled. */
+
+static int
+open_dump_file (index, decl)
+ enum dump_file_index index;
+ tree decl;
{
- char *dumpname;
+ char *dump_name;
+ const char *open_arg;
+ char seq[16];
- TIMEVAR
- (dump_time,
- {
- dumpname = concat (dump_base_name, suffix, NULL);
+ if (! dump_file[index].enabled)
+ return 0;
- if (rtl_dump_file != NULL)
- fclose (rtl_dump_file);
+ timevar_push (TV_DUMP);
+ if (rtl_dump_file != NULL)
+ fclose (rtl_dump_file);
- rtl_dump_file = fopen (dumpname, "a");
-
- if (rtl_dump_file == NULL)
- pfatal_with_name (dumpname);
-
- free (dumpname);
+ sprintf (seq, ".%02d.", index);
- if (function_name)
- fprintf (rtl_dump_file, "\n;; Function %s\n\n", function_name);
- });
-
- return;
-}
+ if (! dump_file[index].initialized)
+ {
+ /* If we've not initialized the files, do so now. */
+ if (graph_dump_format != no_graph
+ && dump_file[index].graph_dump_p)
+ {
+ dump_name = concat (seq, dump_file[index].extension, NULL);
+ clean_graph_dump_file (dump_base_name, dump_name);
+ free (dump_name);
+ }
+ dump_file[index].initialized = 1;
+ open_arg = "w";
+ }
+ else
+ open_arg = "a";
-/* Routine to close a dump file. */
-static void
-close_dump_file (func, insns)
- void (*func) PROTO ((FILE *, rtx));
- rtx insns;
-{
- TIMEVAR
- (dump_time,
- {
- if (func)
- func (rtl_dump_file, insns);
-
- fflush (rtl_dump_file);
- fclose (rtl_dump_file);
+ dump_name = concat (dump_base_name, seq,
+ dump_file[index].extension, NULL);
+
+ rtl_dump_file = fopen (dump_name, open_arg);
+ if (rtl_dump_file == NULL)
+ pfatal_with_name (dump_name);
- rtl_dump_file = NULL;
- });
+ free (dump_name);
- return;
-}
+ if (decl)
+ fprintf (rtl_dump_file, "\n;; Function %s\n\n",
+ decl_printable_name (decl, 2));
-/* Routine to dump rtl into a file. */
-static void
-dump_rtl (suffix, decl, func, insns)
- const char *suffix;
- tree decl;
- void (*func) PROTO ((FILE *, rtx));
- rtx insns;
-{
- open_dump_file (suffix, decl_printable_name (decl, 2));
- close_dump_file (func, insns);
+ timevar_pop (TV_DUMP);
+ return 1;
}
-/* Routine to empty a dump file. */
+/* Routine to close a dump file. */
+
static void
-clean_dump_file (suffix)
- const char *suffix;
+close_dump_file (index, func, insns)
+ enum dump_file_index index;
+ void (*func) PARAMS ((FILE *, rtx));
+ rtx insns;
{
- char * const dumpname = concat (dump_base_name, suffix, NULL);
-
- rtl_dump_file = fopen (dumpname, "w");
+ if (! rtl_dump_file)
+ return;
- if (rtl_dump_file == NULL)
- pfatal_with_name (dumpname);
+ timevar_push (TV_DUMP);
+ if (insns
+ && graph_dump_format != no_graph
+ && dump_file[index].graph_dump_p)
+ {
+ char seq[16];
+ char *suffix;
- free (dumpname);
+ sprintf (seq, ".%02d.", index);
+ suffix = concat (seq, dump_file[index].extension, NULL);
+ print_rtl_graph_with_bb (dump_base_name, suffix, insns);
+ free (suffix);
+ }
+ if (func && insns)
+ func (rtl_dump_file, insns);
+
+ fflush (rtl_dump_file);
fclose (rtl_dump_file);
+
rtl_dump_file = NULL;
-
- return;
+ timevar_pop (TV_DUMP);
}
/* Do any final processing required for the declarations in VEC, of
because many programs have static variables
that exist only to get some text into the object file. */
if (TREE_CODE (decl) == FUNCTION_DECL
- && (warn_unused
+ && (warn_unused_function
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
&& DECL_INITIAL (decl) == 0
&& DECL_EXTERNAL (decl)
/* Warn about static fns or vars defined but not used,
but not about inline functions or static consts
since defining those in header files is normal practice. */
- if (warn_unused
- && ((TREE_CODE (decl) == FUNCTION_DECL && ! DECL_INLINE (decl))
- || (TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
+ if (((warn_unused_function
+ && TREE_CODE (decl) == FUNCTION_DECL && ! DECL_INLINE (decl))
+ || (warn_unused_variable
+ && TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
&& ! DECL_IN_SYSTEM_HEADER (decl)
&& ! DECL_EXTERNAL (decl)
&& ! TREE_PUBLIC (decl)
&& ! TREE_USED (DECL_NAME (decl)))
warning_with_decl (decl, "`%s' defined but not used");
+ timevar_push (TV_SYMOUT);
#ifdef SDB_DEBUGGING_INFO
/* The COFF linker can move initialized global vars to the end.
And that can screw up the symbol ordering.
&& TREE_PUBLIC (decl) && DECL_INITIAL (decl)
&& ! DECL_EXTERNAL (decl)
&& DECL_RTL (decl) != 0)
- TIMEVAR (symout_time, sdbout_symbol (decl, 0));
+ sdbout_symbol (decl, 0);
/* Output COFF information for non-global
file-scope initialized variables. */
&& ! DECL_EXTERNAL (decl)
&& DECL_RTL (decl) != 0
&& GET_CODE (DECL_RTL (decl)) == MEM)
- TIMEVAR (symout_time, sdbout_toplevel_data (decl));
+ sdbout_toplevel_data (decl);
#endif /* SDB_DEBUGGING_INFO */
#ifdef DWARF_DEBUGGING_INFO
/* Output DWARF information for file-scope tentative data object
if (write_symbols == DWARF_DEBUG
&& (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)))
- TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 1));
+ dwarfout_file_scope_decl (decl, 1);
#endif
#ifdef DWARF2_DEBUGGING_INFO
/* Output DWARF2 information for file-scope tentative data object
if (write_symbols == DWARF2_DEBUG
&& (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)))
- TIMEVAR (symout_time, dwarf2out_decl (decl));
+ dwarf2out_decl (decl);
#endif
+ timevar_pop (TV_SYMOUT);
+ }
+}
+
+/* Save the current INPUT_FILENAME and LINENO on the top entry in the
+ INPUT_FILE_STACK. Push a new entry for FILE and LINE, and set the
+ INPUT_FILENAME and LINENO accordingly. */
+
+void
+push_srcloc (file, line)
+ const char *file;
+ int line;
+{
+ struct file_stack *fs;
+
+ if (input_file_stack)
+ {
+ input_file_stack->name = input_filename;
+ input_file_stack->line = lineno;
}
+
+ fs = (struct file_stack *) xmalloc (sizeof (struct file_stack));
+ fs->name = input_filename = file;
+ fs->line = lineno = line;
+ fs->indent_level = 0;
+ fs->next = input_file_stack;
+ input_file_stack = fs;
+ input_file_stack_tick++;
+}
+
+/* Pop the top entry off the stack of presently open source files.
+ Restore the INPUT_FILENAME and LINENO from the new topmost entry on
+ the stack. */
+
+void
+pop_srcloc ()
+{
+ struct file_stack *fs;
+
+ fs = input_file_stack;
+ input_file_stack = fs->next;
+ free (fs);
+ input_file_stack_tick++;
+ /* The initial souce file is never popped. */
+ if (!input_file_stack)
+ abort ();
+ input_filename = input_file_stack->name;
+ lineno = input_file_stack->line;
}
/* Compile an entire file of output from cpp, named NAME.
static void
compile_file (name)
- char *name;
+ const char *name;
{
tree globals;
- int start_time;
int name_specified = name != 0;
if (dump_base_name == 0)
dump_base_name = name ? name : "gccdump";
- parse_time = 0;
- varconst_time = 0;
- integration_time = 0;
- jump_time = 0;
- cse_time = 0;
- gcse_time = 0;
- loop_time = 0;
- cse2_time = 0;
- branch_prob_time = 0;
- flow_time = 0;
- combine_time = 0;
- regmove_time = 0;
- sched_time = 0;
- local_alloc_time = 0;
- global_alloc_time = 0;
- flow2_time = 0;
- peephole2_time = 0;
- sched2_time = 0;
- dbr_sched_time = 0;
- shorten_branch_time = 0;
- stack_reg_time = 0;
- final_time = 0;
- symout_time = 0;
- dump_time = 0;
+ /* Start timing total execution time. */
+ init_timevar ();
+ timevar_start (TV_TOTAL);
+
/* Initialize data in various passes. */
init_obstacks ();
pfatal_with_name (aux_info_file_name);
}
- /* Clear the dump files. */
- if (rtl_dump)
- clean_dump_file (".00.rtl");
- if (jump_opt_dump)
- {
- clean_dump_file (".01.jump");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".01.jump");
- }
- if (cse_dump)
- {
- clean_dump_file (".02.cse");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".02.cse");
- }
- if (addressof_dump)
- {
- clean_dump_file (".03.addressof");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".03.addressof");
- }
- if (gcse_dump)
- {
- clean_dump_file (".04.gcse");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".04.gcse");
- }
- if (loop_dump)
- {
- clean_dump_file (".05.loop");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".05.loop");
- }
- if (cse2_dump)
- {
- clean_dump_file (".06.cse2");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".06.cse2");
- }
- if (branch_prob_dump)
- {
- clean_dump_file (".07.bp");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".07.bp");
- }
- if (flow_dump)
- {
- clean_dump_file (".08.flow");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".08.flow");
- }
- if (combine_dump)
- {
- clean_dump_file (".09.combine");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".09.combine");
- }
- if (regmove_dump)
- {
- clean_dump_file (".10.regmove");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".10.regmove");
- }
-#ifdef INSN_SCHEDULING
- if (sched_dump)
- {
- clean_dump_file (".11.sched");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".11.sched");
- }
-#endif
- if (local_reg_dump)
- {
- clean_dump_file (".12.lreg");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".12.lreg");
- }
- if (global_reg_dump)
- {
- clean_dump_file (".13.greg");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".13.greg");
- }
- if (flow2_dump)
- {
- clean_dump_file (".14.flow2");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".14.flow2");
- }
-#ifdef HAVE_peephole2
- if (peephole2_dump)
- {
- clean_dump_file (".15.peephole2");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".15.peephole2");
- }
-#endif
-#ifdef INSN_SCHEDULING
- if (sched2_dump)
- {
- clean_dump_file (".16.sched2");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".16.sched2");
- }
-#endif
- if (jump2_opt_dump)
- {
- clean_dump_file (".17.jump2");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".17.jump2");
- }
-#ifdef MACHINE_DEPENDENT_REORG
- if (mach_dep_reorg_dump)
- {
- clean_dump_file (".18.mach");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".18.mach");
- }
-#endif
-#ifdef DELAY_SLOTS
- if (dbr_sched_dump)
- {
- clean_dump_file (".19.dbr");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".19.dbr");
- }
-#endif
-#ifdef STACK_REGS
- if (stack_reg_dump)
- {
- clean_dump_file (".20.stack");
- if (graph_dump_format != no_graph)
- clean_graph_dump_file (dump_base_name, ".20.stack");
- }
-#endif
-
/* Open assembler code output file. */
if (flag_syntax_only)
asm_out_file = stdout;
else
{
- int len = strlen (dump_base_name);
- register char *dumpname = (char *) xmalloc (len + 6);
- strcpy (dumpname, dump_base_name);
- strip_off_ending (dumpname, len);
- strcat (dumpname, ".s");
if (asm_file_name == 0)
- asm_file_name = xstrdup (dumpname);
+ {
+ int len = strlen (dump_base_name);
+ char *dumpname = (char *) xmalloc (len + 6);
+ memcpy (dumpname, dump_base_name, len + 1);
+ strip_off_ending (dumpname, len);
+ strcat (dumpname, ".s");
+ asm_file_name = dumpname;
+ }
if (!strcmp (asm_file_name, "-"))
asm_out_file = stdout;
else
#endif
}
- if (ggc_p)
+ if (ggc_p && name != 0)
name = ggc_alloc_string (name, strlen (name));
+
input_filename = name;
/* Put an entry on the input file stack for the main input file. */
- input_file_stack
- = (struct file_stack *) xmalloc (sizeof (struct file_stack));
- input_file_stack->next = 0;
- input_file_stack->name = input_filename;
+ push_srcloc (input_filename, 0);
/* Perform language-specific initialization.
This may set main_input_filename. */
/* If dbx symbol table desired, initialize writing it
and output the predefined types. */
+ timevar_push (TV_SYMOUT);
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
- TIMEVAR (symout_time, dbxout_init (asm_out_file, main_input_filename,
- getdecls ()));
+ dbxout_init (asm_out_file, main_input_filename, getdecls ());
#endif
#ifdef SDB_DEBUGGING_INFO
if (write_symbols == SDB_DEBUG)
- TIMEVAR (symout_time, sdbout_init (asm_out_file, main_input_filename,
- getdecls ()));
+ sdbout_init (asm_out_file, main_input_filename, getdecls ());
#endif
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
- TIMEVAR (symout_time, dwarfout_init (asm_out_file, main_input_filename));
+ dwarfout_init (asm_out_file, main_input_filename);
#endif
#ifdef DWARF2_UNWIND_INFO
if (dwarf2out_do_frame ())
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
- TIMEVAR (symout_time, dwarf2out_init (asm_out_file, main_input_filename));
+ dwarf2out_init (asm_out_file, main_input_filename);
#endif
+ timevar_pop (TV_SYMOUT);
/* Initialize yet another pass. */
init_final (main_input_filename);
init_branch_prob (dump_base_name);
- start_time = get_run_time ();
+ timevar_push (TV_PARSE);
/* Call the parser, which parses the entire file
(calling rest_of_compilation for each function). */
if (yyparse () != 0)
{
if (errorcount == 0)
- notice ("Errors detected in input file (your bison.simple is out of date)\n");
+ fnotice (stderr, "Errors detected in input file (your bison.simple is out of date)\n");
/* In case there were missing closebraces,
get us back to the global binding level. */
/* Compilation is now finished except for writing
what's left of the symbol table output. */
- parse_time += get_run_time () - start_time;
-
- parse_time -= integration_time;
- parse_time -= varconst_time;
+ timevar_pop (TV_PARSE);
if (flag_syntax_only)
goto finish_syntax;
{
int len = list_length (globals);
- tree *vec = (tree *) alloca (sizeof (tree) * len);
+ tree *vec = (tree *) xmalloc (sizeof (tree) * len);
int i;
tree decl;
/* Now that all possible functions have been output, we can dump
the exception table. */
+#ifndef IA64_UNWIND_INFO
output_exception_table ();
-
+#endif
+ free_exception_table ();
+
check_global_declarations (vec, len);
+
+ /* Clean up. */
+ free (vec);
}
/* Write out any pending weak symbol declarations. */
weak_finish ();
/* Do dbx symbols */
+ timevar_push (TV_SYMOUT);
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
- TIMEVAR (symout_time,
- {
- dbxout_finish (asm_out_file, main_input_filename);
- });
+ dbxout_finish (asm_out_file, main_input_filename);
#endif
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
- TIMEVAR (symout_time,
- {
- dwarfout_finish ();
- });
+ dwarfout_finish ();
#endif
#ifdef DWARF2_UNWIND_INFO
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
- TIMEVAR (symout_time,
- {
- dwarf2out_finish ();
- });
+ dwarf2out_finish ();
#endif
+ timevar_pop (TV_SYMOUT);
/* Output some stuff at end of file if nec. */
end_final (dump_base_name);
- if (branch_prob_dump)
- open_dump_file (".07.bp", NULL);
-
- TIMEVAR (dump_time, end_branch_prob (rtl_dump_file));
-
- if (branch_prob_dump)
- close_dump_file (NULL, NULL_RTX);
+ if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
+ {
+ timevar_push (TV_DUMP);
+ open_dump_file (DFI_bp, NULL);
+
+ end_branch_prob ();
+
+ close_dump_file (DFI_bp, NULL, NULL_RTX);
+ timevar_pop (TV_DUMP);
+ }
#ifdef ASM_FILE_END
ASM_FILE_END (asm_out_file);
#endif
-
/* Language-specific end of compilation actions. */
finish_syntax:
lang_finish ();
unlink (aux_info_file_name);
}
- if (combine_dump)
+ if (optimize > 0 && open_dump_file (DFI_combine, NULL))
{
- open_dump_file (".09.combine", NULL);
- TIMEVAR (dump_time, dump_combine_total_stats (rtl_dump_file));
- close_dump_file (NULL, NULL_RTX);
+ timevar_push (TV_DUMP);
+ dump_combine_total_stats (rtl_dump_file);
+ close_dump_file (DFI_combine, NULL, NULL_RTX);
+ timevar_pop (TV_DUMP);
}
/* Close non-debugging input and output files. Take special care to note
/* Do whatever is necessary to finish printing the graphs. */
if (graph_dump_format != no_graph)
{
- if (jump_opt_dump)
- finish_graph_dump_file (dump_base_name, ".01.jump");
- if (cse_dump)
- finish_graph_dump_file (dump_base_name, ".02.cse");
- if (addressof_dump)
- finish_graph_dump_file (dump_base_name, ".03.addressof");
- if (gcse_dump)
- finish_graph_dump_file (dump_base_name, ".04.gcse");
- if (loop_dump)
- finish_graph_dump_file (dump_base_name, ".05.loop");
- if (cse2_dump)
- finish_graph_dump_file (dump_base_name, ".06.cse2");
- if (branch_prob_dump)
- finish_graph_dump_file (dump_base_name, ".07.bp");
- if (flow_dump)
- finish_graph_dump_file (dump_base_name, ".08.flow");
- if (combine_dump)
- finish_graph_dump_file (dump_base_name, ".09.combine");
- if (regmove_dump)
- finish_graph_dump_file (dump_base_name, ".10.regmove");
-#ifdef INSN_SCHEDULING
- if (sched_dump)
- finish_graph_dump_file (dump_base_name, ".11.sched");
-#endif
- if (local_reg_dump)
- finish_graph_dump_file (dump_base_name, ".12.lreg");
- if (global_reg_dump)
- finish_graph_dump_file (dump_base_name, ".13.greg");
- if (flow2_dump)
- finish_graph_dump_file (dump_base_name, ".14.flow2");
-#ifdef HAVE_peephole2
- if (flow2_dump)
- finish_graph_dump_file (dump_base_name, ".15.peephole2");
-#endif
-#ifdef INSN_SCHEDULING
- if (sched2_dump)
- finish_graph_dump_file (dump_base_name, ".16.sched2");
-#endif
- if (jump2_opt_dump)
- finish_graph_dump_file (dump_base_name, ".17.jump2");
-#ifdef MACHINE_DEPENDENT_REORG
- if (mach_dep_reorg_dump)
- finish_graph_dump_file (dump_base_name, ".18.mach");
-#endif
-#ifdef DELAY_SLOTS
- if (dbr_sched_dump)
- finish_graph_dump_file (dump_base_name, ".19.dbr");
-#endif
-#ifdef STACK_REGS
- if (stack_reg_dump)
- finish_graph_dump_file (dump_base_name, ".20.stack");
-#endif
+ int i;
+
+ for (i = 0; i < DFI_MAX; ++i)
+ if (dump_file[i].initialized && dump_file[i].graph_dump_p)
+ {
+ char seq[16];
+ char *suffix;
+
+ sprintf (seq, ".%02d.", i);
+ suffix = concat (seq, dump_file[i].extension, NULL);
+ finish_graph_dump_file (dump_base_name, suffix);
+ free (suffix);
+ }
}
/* Free up memory for the benefit of leak detectors. */
free_reg_info ();
+ /* Stop timing total execution time. */
+ timevar_stop (TV_TOTAL);
+
/* Print the times. */
if (! quiet_flag)
- {
- all_time = get_run_time ();
-
- fprintf (stderr,"\n");
-
- print_time ("parse", parse_time);
- print_time ("integration", integration_time);
- print_time ("jump", jump_time);
- print_time ("cse", cse_time);
- print_time ("gcse", gcse_time);
- print_time ("loop", loop_time);
- print_time ("cse2", cse2_time);
- print_time ("branch-prob", branch_prob_time);
- print_time ("flow", flow_time);
- print_time ("combine", combine_time);
- print_time ("regmove", regmove_time);
-#ifdef INSN_SCHEDULING
- print_time ("sched", sched_time);
-#endif
- print_time ("local-alloc", local_alloc_time);
- print_time ("global-alloc", global_alloc_time);
- print_time ("flow2", flow2_time);
-#ifdef HAVE_peephole2
- print_time ("peephole2", peephole2_time);
-#endif
-#ifdef INSN_SCHEDULING
- print_time ("sched2", sched2_time);
-#endif
-#ifdef DELAY_SLOTS
- print_time ("dbranch", dbr_sched_time);
-#endif
- print_time ("shorten-branch", shorten_branch_time);
-#ifdef STACK_REGS
- print_time ("stack-reg", stack_reg_time);
-#endif
- print_time ("final", final_time);
- print_time ("varconst", varconst_time);
- print_time ("symout", symout_time);
- print_time ("dump", dump_time);
- if (ggc_p)
- print_time ("gc", gc_time);
- }
+ timevar_print (stderr);
}
\f
/* This is called from various places for FUNCTION_DECL, VAR_DECL,
but we need to treat them as if they were. */
if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
|| TREE_CODE (decl) == FUNCTION_DECL)
- TIMEVAR (varconst_time,
- {
- make_decl_rtl (decl, asmspec, top_level);
- /* Initialized extern variable exists to be replaced
- with its value, or represents something that will be
- output in another file. */
- if (! (TREE_CODE (decl) == VAR_DECL
- && DECL_EXTERNAL (decl) && TREE_READONLY (decl)
- && DECL_INITIAL (decl) != 0
- && DECL_INITIAL (decl) != error_mark_node))
- /* Don't output anything
- when a tentative file-scope definition is seen.
- But at end of compilation, do output code for them. */
- if (! (! at_end && top_level
- && (DECL_INITIAL (decl) == 0
- || DECL_INITIAL (decl) == error_mark_node)))
- assemble_variable (decl, top_level, at_end, 0);
- if (decl == last_assemble_variable_decl)
- {
- ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
- top_level, at_end);
- }
- });
+ {
+ timevar_push (TV_VARCONST);
+ make_decl_rtl (decl, asmspec, top_level);
+ /* Initialized extern variable exists to be replaced
+ with its value, or represents something that will be
+ output in another file. */
+ if (! (TREE_CODE (decl) == VAR_DECL
+ && DECL_EXTERNAL (decl) && TREE_READONLY (decl)
+ && DECL_INITIAL (decl) != 0
+ && DECL_INITIAL (decl) != error_mark_node))
+ /* Don't output anything
+ when a tentative file-scope definition is seen.
+ But at end of compilation, do output code for them. */
+ if (! (! at_end && top_level
+ && (DECL_INITIAL (decl) == 0
+ || DECL_INITIAL (decl) == error_mark_node)))
+ assemble_variable (decl, top_level, at_end, 0);
+ if (decl == last_assemble_variable_decl)
+ {
+ ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
+ top_level, at_end);
+ }
+ timevar_pop (TV_VARCONST);
+ }
else if (DECL_REGISTER (decl) && asmspec != 0)
{
if (decode_reg_name (asmspec) >= 0)
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
else if ((write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
&& TREE_CODE (decl) == TYPE_DECL)
- TIMEVAR (symout_time, dbxout_symbol (decl, 0));
+ {
+ timevar_push (TV_SYMOUT);
+ dbxout_symbol (decl, 0);
+ timevar_pop (TV_SYMOUT);
+ }
#endif
#ifdef SDB_DEBUGGING_INFO
else if (write_symbols == SDB_DEBUG && top_level
&& TREE_CODE (decl) == TYPE_DECL)
- TIMEVAR (symout_time, sdbout_symbol (decl, 0));
+ {
+ timevar_push (TV_SYMOUT);
+ sdbout_symbol (decl, 0);
+ timevar_pop (TV_SYMOUT);
+ }
#endif
}
int toplev ATTRIBUTE_UNUSED;
#endif
{
+ timevar_push (TV_SYMOUT);
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
- TIMEVAR (symout_time, dbxout_symbol (TYPE_STUB_DECL (type), !toplev));
+ dbxout_symbol (TYPE_STUB_DECL (type), !toplev);
#endif
#ifdef SDB_DEBUGGING_INFO
if (write_symbols == SDB_DEBUG)
- TIMEVAR (symout_time, sdbout_symbol (TYPE_STUB_DECL (type), !toplev));
+ sdbout_symbol (TYPE_STUB_DECL (type), !toplev);
+#endif
+ timevar_pop (TV_SYMOUT);
+}
+
+/* DECL is an inline function, whose body is present, but which is not
+ being output at this point. (We're putting that off until we need
+ to do it.) If there are any actions that need to take place,
+ including the emission of debugging information for the function,
+ this is where they should go. This function may be called by
+ language-dependent code for front-ends that do not even generate
+ RTL for functions that don't need to be put out. */
+
+void
+note_deferral_of_defined_inline_function (decl)
+ tree decl ATTRIBUTE_UNUSED;
+{
+#ifdef DWARF_DEBUGGING_INFO
+ /* Generate the DWARF info for the "abstract" instance of a function
+ which we may later generate inlined and/or out-of-line instances
+ of. */
+ if (write_symbols == DWARF_DEBUG && DECL_INLINE (decl))
+ {
+ /* The front-end may not have set CURRENT_FUNCTION_DECL, but the
+ DWARF code expects it to be set in this case. Intuitively,
+ DECL is the function we just finished defining, so setting
+ CURRENT_FUNCTION_DECL is sensible. */
+ tree saved_cfd = current_function_decl;
+ current_function_decl = decl;
+
+ /* Let the DWARF code do its work. */
+ set_decl_abstract_flags (decl, 1);
+ dwarfout_file_scope_decl (decl, 0);
+ set_decl_abstract_flags (decl, 0);
+
+ /* Reset CURRENT_FUNCTION_DECL. */
+ current_function_decl = saved_cfd;
+ }
#endif
}
tree decl;
{
register rtx insns;
- int start_time = get_run_time ();
int tem;
- /* Nonzero if we have saved the original DECL_INITIAL of the function,
- to be restored after we finish compiling the function
- (for use when compiling inline calls to this function). */
- tree saved_block_tree = 0;
- /* Likewise, for DECL_ARGUMENTS. */
- tree saved_arguments = 0;
int failure = 0;
int rebuild_label_notes_after_reload;
+ timevar_push (TV_REST_OF_COMPILATION);
+
+ /* When processing delayed functions, prepare_function_start() won't
+ have been run to re-initialize it. */
+ cse_not_expected = ! optimize;
+
+ /* First, make sure that NOTE_BLOCK is set correctly for each
+ NOTE_INSN_BLOCK_BEG/NOTE_INSN_BLOCK_END note. */
+ if (!cfun->x_whole_function_mode_p)
+ identify_blocks ();
+
+ /* Then remove any notes we don't need. That will make iterating
+ over the instruction sequence faster, and allow the garbage
+ collector to reclaim the memory used by the notes. */
+ remove_unnecessary_notes ();
+
+ /* In function-at-a-time mode, we do not attempt to keep the BLOCK
+ tree in sensible shape. So, we just recalculate it here. */
+ if (cfun->x_whole_function_mode_p)
+ reorder_blocks ();
+
/* If we are reconsidering an inline function
at the end of compilation, skip the stuff for making it inline. */
generating code for this one is not only not necessary but will
confuse some debugging output writers. */
for (parent = DECL_CONTEXT (current_function_decl);
- parent != 0; parent = DECL_CONTEXT (parent))
+ parent != NULL_TREE;
+ parent = get_containing_scope (parent))
if (TREE_CODE (parent) == FUNCTION_DECL
&& DECL_INLINE (parent) && DECL_EXTERNAL (parent))
{
/* If requested, consider whether to make this function inline. */
if (DECL_INLINE (decl) || flag_inline_functions)
- TIMEVAR (integration_time,
- {
- lose = function_cannot_inline_p (decl);
- if (lose || ! optimize)
- {
- if (warn_inline && DECL_INLINE (decl))
- warning_with_decl (decl, lose);
- DECL_ABSTRACT_ORIGIN (decl) = 0;
- /* Don't really compile an extern inline function.
- If we can't make it inline, pretend
- it was only declared. */
- if (DECL_EXTERNAL (decl))
- {
- DECL_INITIAL (decl) = 0;
- goto exit_rest_of_compilation;
- }
- }
- else
- /* ??? Note that this has the effect of making it look
- like "inline" was specified for a function if we choose
- to inline it. This isn't quite right, but it's
- probably not worth the trouble to fix. */
- inlinable = DECL_INLINE (decl) = 1;
- });
+ {
+ timevar_push (TV_INTEGRATION);
+ lose = function_cannot_inline_p (decl);
+ timevar_pop (TV_INTEGRATION);
+ if (lose || ! optimize)
+ {
+ if (warn_inline && DECL_INLINE (decl))
+ warning_with_decl (decl, lose);
+ DECL_ABSTRACT_ORIGIN (decl) = 0;
+ /* Don't really compile an extern inline function.
+ If we can't make it inline, pretend
+ it was only declared. */
+ if (DECL_EXTERNAL (decl))
+ {
+ DECL_INITIAL (decl) = 0;
+ goto exit_rest_of_compilation;
+ }
+ }
+ else
+ /* ??? Note that this has the effect of making it look
+ like "inline" was specified for a function if we choose
+ to inline it. This isn't quite right, but it's
+ probably not worth the trouble to fix. */
+ inlinable = DECL_INLINE (decl) = 1;
+ }
insns = get_insns ();
/* Dump the rtl code if we are dumping rtl. */
- if (rtl_dump)
+ if (open_dump_file (DFI_rtl, decl))
{
- open_dump_file (".00.rtl", decl_printable_name (decl, 2));
-
if (DECL_SAVED_INSNS (decl))
fprintf (rtl_dump_file, ";; (integrable)\n\n");
-
- close_dump_file (print_rtl, insns);
+ close_dump_file (DFI_rtl, print_rtl, insns);
}
/* If function is inline, and we don't yet know whether to
for those functions that need to be output. Also defer those
functions that we are supposed to defer. */
- if (inlinable)
- DECL_DEFER_OUTPUT (decl) = 1;
-
- if (DECL_DEFER_OUTPUT (decl)
+ if (inlinable
|| (DECL_INLINE (decl)
&& ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)
&& ! flag_keep_inline_functions)
|| DECL_EXTERNAL (decl))))
- {
- DECL_DEFER_OUTPUT (decl) = 1;
+ DECL_DEFER_OUTPUT (decl) = 1;
+
+ if (DECL_INLINE (decl))
+ /* DWARF wants seperate debugging info for abstract and
+ concrete instances of all inline functions, including those
+ declared inline but not inlined, and those inlined even
+ though they weren't declared inline. Conveniently, that's
+ what DECL_INLINE means at this point. */
+ note_deferral_of_defined_inline_function (decl);
+ if (DECL_DEFER_OUTPUT (decl))
+ {
/* If -Wreturn-type, we have to do a bit of compilation.
However, if we just fall through we will call
save_for_inline_copying() which results in excessive
int saved_optimize = optimize;
optimize = 0;
find_exception_handler_labels ();
- jump_optimize (get_insns(), !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
+ jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
!JUMP_AFTER_REGSCAN);
optimize = saved_optimize;
}
-#ifdef DWARF_DEBUGGING_INFO
- /* Generate the DWARF info for the "abstract" instance
- of a function which we may later generate inlined and/or
- out-of-line instances of. */
- if (write_symbols == DWARF_DEBUG)
- {
- set_decl_abstract_flags (decl, 1);
- TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 0));
- set_decl_abstract_flags (decl, 0);
- }
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
- /* Generate the DWARF2 info for the "abstract" instance
- of a function which we may later generate inlined and/or
- out-of-line instances of. */
- if (write_symbols == DWARF2_DEBUG)
- {
- set_decl_abstract_flags (decl, 1);
- TIMEVAR (symout_time, dwarf2out_decl (decl));
- set_decl_abstract_flags (decl, 0);
- }
-#endif
- TIMEVAR (integration_time, save_for_inline_nocopy (decl));
+ current_function_nothrow = nothrow_function_p ();
+ if (current_function_nothrow)
+ /* Now we know that this can't throw; set the flag for the benefit
+ of other functions later in this translation unit. */
+ TREE_NOTHROW (current_function_decl) = 1;
+
+ timevar_push (TV_INTEGRATION);
+ save_for_inline_nocopy (decl);
+ timevar_pop (TV_INTEGRATION);
DECL_SAVED_INSNS (decl)->inlinable = inlinable;
goto exit_rest_of_compilation;
}
goto exit_rest_of_compilation;
}
+ init_EXPR_INSN_LIST_cache ();
+
+ if (ggc_p)
+ ggc_collect ();
+
/* Initialize some variables used by the optimizers. */
init_function_for_compilation ();
/* Don't return yet if -Wreturn-type; we need to do jump_optimize. */
if ((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type)
- {
- goto exit_rest_of_compilation;
- }
+ goto exit_rest_of_compilation;
/* Emit code to get eh context, if needed. */
emit_eh_context ();
+ /* We may have potential sibling or tail recursion sites. Select one
+ (of possibly multiple) methods of performing the call. */
+ if (flag_optimize_sibling_calls)
+ {
+ timevar_push (TV_JUMP);
+ open_dump_file (DFI_sibling, decl);
+
+ optimize_sibling_and_tail_recursive_calls ();
+
+ close_dump_file (DFI_sibling, print_rtl, get_insns ());
+ timevar_pop (TV_JUMP);
+ }
+
#ifdef FINALIZE_PIC
/* If we are doing position-independent code generation, now
is the time to output special prologues and epilogues.
insns = get_insns ();
/* Copy any shared structure that should not be shared. */
-
- unshare_all_rtl (insns);
-
- init_EXPR_INSN_LIST_cache ();
+ unshare_all_rtl (current_function_decl, insns);
#ifdef SETJMP_VIA_SAVE_AREA
/* This must be performed before virutal register instantiation. */
#endif
/* Instantiate all virtual registers. */
-
- instantiate_virtual_regs (current_function_decl, get_insns ());
-
- /* See if we have allocated stack slots that are not directly addressable.
- If so, scan all the insns and create explicit address computation
- for all references to such slots. */
- /* fixup_stack_slots (); */
+ instantiate_virtual_regs (current_function_decl, insns);
/* Find all the EH handlers. */
find_exception_handler_labels ();
- if (jump_opt_dump)
- open_dump_file (".01.jump", decl_printable_name (decl, 2));
+ open_dump_file (DFI_jump, decl);
/* Always do one jump optimization pass to ensure that JUMP_LABEL fields
are initialized and to compute whether control can drop off the end
of the function. */
- TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
- TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
- JUMP_AFTER_REGSCAN));
+
+ timevar_push (TV_JUMP);
+ /* Turn NOTE_INSN_EXPECTED_VALUE into REG_BR_PROB. Do this
+ before jump optimization switches branch directions. */
+ expected_value_to_br_prob ();
+
+ reg_scan (insns, max_reg_num (), 0);
+ jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
+ JUMP_AFTER_REGSCAN);
+
+ timevar_pop (TV_JUMP);
/* Now is when we stop if -fsyntax-only and -Wreturn-type. */
if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl))
- goto exit_rest_of_compilation;
+ {
+ close_dump_file (DFI_jump, print_rtl, insns);
+ goto exit_rest_of_compilation;
+ }
+
+ timevar_push (TV_JUMP);
+
+ if (optimize > 0)
+ {
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (insns);
+
+ /* ??? Run if-conversion before delete_null_pointer_checks,
+ since the later does not preserve the CFG. This should
+ be changed -- no since converting if's that are going to
+ be deleted. */
+ timevar_push (TV_IFCVT);
+ if_convert (0);
+ timevar_pop (TV_IFCVT);
+
+ /* Try to identify useless null pointer tests and delete them. */
+ if (flag_delete_null_pointer_checks)
+ delete_null_pointer_checks (insns);
+ }
- /* Try to identify useless null pointer tests and delete them. */
- if (flag_delete_null_pointer_checks)
- TIMEVAR (jump_time, delete_null_pointer_checks (get_insns ()));
+ /* Jump optimization, and the removal of NULL pointer checks, may
+ have reduced the number of instructions substantially. CSE, and
+ future passes, allocate arrays whose dimensions involve the
+ maximum instruction UID, so if we can reduce the maximum UID
+ we'll save big on memory. */
+ renumber_insns (rtl_dump_file);
+ timevar_pop (TV_JUMP);
- /* Dump rtl code after jump, if we are doing that. */
- if (jump_opt_dump)
- close_dump_file (print_rtl, insns);
+ close_dump_file (DFI_jump, print_rtl, insns);
if (ggc_p)
ggc_collect ();
if (optimize > 0)
{
- if (cse_dump)
- open_dump_file (".02.cse", decl_printable_name (decl, 2));
+ open_dump_file (DFI_cse, decl);
+ timevar_push (TV_CSE);
- TIMEVAR (cse_time, reg_scan (insns, max_reg_num (), 1));
+ reg_scan (insns, max_reg_num (), 1);
if (flag_thread_jumps)
- TIMEVAR (jump_time, thread_jumps (insns, max_reg_num (), 1));
+ {
+ timevar_push (TV_JUMP);
+ thread_jumps (insns, max_reg_num (), 1);
+ timevar_pop (TV_JUMP);
+ }
+
+ tem = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
- TIMEVAR (cse_time, tem = cse_main (insns, max_reg_num (),
- 0, rtl_dump_file));
/* If we are not running the second CSE pass, then we are no longer
expecting CSE to be run. */
cse_not_expected = !flag_rerun_cse_after_loop;
if (tem || optimize > 1)
- TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
- !JUMP_NOOP_MOVES,
- !JUMP_AFTER_REGSCAN));
+ {
+ timevar_push (TV_JUMP);
+ jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
+ !JUMP_AFTER_REGSCAN);
+ timevar_pop (TV_JUMP);
+ }
/* Run this after jump optmizations remove all the unreachable code
so that unreachable code will not keep values live. */
- TIMEVAR (cse_time, delete_trivially_dead_insns (insns, max_reg_num ()));
+ delete_trivially_dead_insns (insns, max_reg_num ());
/* Try to identify useless null pointer tests and delete them. */
if (flag_delete_null_pointer_checks)
- TIMEVAR (jump_time, delete_null_pointer_checks (get_insns ()));
+ {
+ timevar_push (TV_JUMP);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- /* Dump rtl code after cse, if we are doing that. */
+ cleanup_cfg (insns);
- if (cse_dump)
- {
- close_dump_file (print_rtl, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".02.cse", insns);
+ delete_null_pointer_checks (insns);
+ timevar_pop (TV_JUMP);
}
+
+ /* The second pass of jump optimization is likely to have
+ removed a bunch more instructions. */
+ renumber_insns (rtl_dump_file);
+
+ timevar_pop (TV_CSE);
+ close_dump_file (DFI_cse, print_rtl, insns);
}
+ open_dump_file (DFI_addressof, decl);
+
purge_addressof (insns);
reg_scan (insns, max_reg_num (), 1);
- if (addressof_dump)
- {
- dump_rtl (".03.addressof", decl, print_rtl, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".03.addressof", insns);
- }
+ close_dump_file (DFI_addressof, print_rtl, insns);
if (ggc_p)
ggc_collect ();
+ if (optimize > 0 && flag_ssa)
+ {
+ /* Convert to SSA form. */
+
+ timevar_push (TV_TO_SSA);
+ open_dump_file (DFI_ssa, decl);
+
+ find_basic_blocks (insns, max_reg_num(), rtl_dump_file);
+ cleanup_cfg (insns);
+ convert_to_ssa ();
+
+ close_dump_file (DFI_ssa, print_rtl_with_bb, insns);
+ timevar_pop (TV_TO_SSA);
+
+ /* Currently, there's nothing to do in SSA form. */
+
+ /* Convert from SSA form. */
+
+ timevar_push (TV_FROM_SSA);
+ open_dump_file (DFI_ussa, decl);
+
+ convert_from_ssa ();
+ /* New registers have been created. Rescan their usage. */
+ reg_scan (insns, max_reg_num (), 1);
+ /* Life analysis used in SSA adds log_links but these
+ shouldn't be there until the flow stage, so clear
+ them away. */
+ clear_log_links (insns);
+
+ close_dump_file (DFI_ussa, print_rtl_with_bb, insns);
+ timevar_pop (TV_FROM_SSA);
+
+ if (ggc_p)
+ ggc_collect ();
+ }
+
/* Perform global cse. */
if (optimize > 0 && flag_gcse)
{
- if (gcse_dump)
- open_dump_file (".04.gcse", decl_printable_name (decl, 2));
+ timevar_push (TV_GCSE);
+ open_dump_file (DFI_gcse, decl);
- TIMEVAR (gcse_time, tem = gcse_main (insns, rtl_dump_file));
+ find_basic_blocks (insns, max_reg_num(), rtl_dump_file);
+ cleanup_cfg (insns);
+ tem = gcse_main (insns, rtl_dump_file);
/* If gcse altered any jumps, rerun jump optimizations to clean
things up. */
if (tem)
{
- TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
- !JUMP_NOOP_MOVES,
- !JUMP_AFTER_REGSCAN));
+ timevar_push (TV_JUMP);
+ jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
+ !JUMP_AFTER_REGSCAN);
+ timevar_pop (TV_JUMP);
}
- if (gcse_dump)
- {
- close_dump_file (print_rtl, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".04.gcse", insns);
- }
+ close_dump_file (DFI_gcse, print_rtl, insns);
+ timevar_pop (TV_GCSE);
if (ggc_p)
ggc_collect ();
}
+
/* Move constant computations out of loops. */
if (optimize > 0)
{
- if (loop_dump)
- open_dump_file (".05.loop", decl_printable_name (decl, 2));
-
- TIMEVAR
- (loop_time,
- {
- if (flag_rerun_loop_opt)
- {
- /* We only want to perform unrolling once. */
-
- loop_optimize (insns, rtl_dump_file, 0, 0);
+ timevar_push (TV_LOOP);
+ open_dump_file (DFI_loop, decl);
+
+ if (flag_rerun_loop_opt)
+ {
+ /* We only want to perform unrolling once. */
-
- /* The first call to loop_optimize makes some instructions
- trivially dead. We delete those instructions now in the
- hope that doing so will make the heuristics in loop work
- better and possibly speed up compilation. */
- delete_trivially_dead_insns (insns, max_reg_num ());
-
- /* The regscan pass is currently necessary as the alias
- analysis code depends on this information. */
- reg_scan (insns, max_reg_num (), 1);
- }
- loop_optimize (insns, rtl_dump_file, flag_unroll_loops, 1);
- });
+ loop_optimize (insns, rtl_dump_file, 0);
- /* Dump rtl code after loop opt, if we are doing that. */
+ /* The first call to loop_optimize makes some instructions
+ trivially dead. We delete those instructions now in the
+ hope that doing so will make the heuristics in loop work
+ better and possibly speed up compilation. */
+ delete_trivially_dead_insns (insns, max_reg_num ());
- if (loop_dump)
- {
- close_dump_file (print_rtl, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".05.loop", insns);
+ /* The regscan pass is currently necessary as the alias
+ analysis code depends on this information. */
+ reg_scan (insns, max_reg_num (), 1);
}
+ loop_optimize (insns, rtl_dump_file, (flag_unroll_loops ? LOOP_UNROLL : 0) | LOOP_BCT);
+
+ close_dump_file (DFI_loop, print_rtl, insns);
+ timevar_pop (TV_LOOP);
if (ggc_p)
ggc_collect ();
}
- /* ??? Well, nearly. If HAVE_conditional_arithmetic, jump_optimize
- has put off all if-conversion until "after CSE". If we put this
- off any longer we may miss out doing if-conversion entirely. */
- cse_not_expected = 1;
-
if (optimize > 0)
{
- if (cse2_dump)
- open_dump_file (".06.cse2", decl_printable_name (decl, 2));
+ timevar_push (TV_CSE2);
+ open_dump_file (DFI_cse2, decl);
if (flag_rerun_cse_after_loop)
{
the second CSE pass to do a better job. Jump_optimize can change
max_reg_num so we must rerun reg_scan afterwards.
??? Rework to not call reg_scan so often. */
- TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
- TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
- !JUMP_NOOP_MOVES,
- JUMP_AFTER_REGSCAN));
+ timevar_push (TV_JUMP);
+
+ reg_scan (insns, max_reg_num (), 0);
+ jump_optimize (insns, !JUMP_CROSS_JUMP,
+ !JUMP_NOOP_MOVES, JUMP_AFTER_REGSCAN);
+
+ timevar_push (TV_IFCVT);
+
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (insns);
+ if_convert (0);
+
+ timevar_pop(TV_IFCVT);
+
+ timevar_pop (TV_JUMP);
- TIMEVAR (cse2_time, reg_scan (insns, max_reg_num (), 0));
- TIMEVAR (cse2_time, tem = cse_main (insns, max_reg_num (),
- 1, rtl_dump_file));
+ reg_scan (insns, max_reg_num (), 0);
+ tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file);
+
if (tem)
- TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
- !JUMP_NOOP_MOVES,
- !JUMP_AFTER_REGSCAN));
+ {
+ timevar_push (TV_JUMP);
+ jump_optimize (insns, !JUMP_CROSS_JUMP,
+ !JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN);
+ timevar_pop (TV_JUMP);
+ }
}
if (flag_thread_jumps)
{
/* This pass of jump threading straightens out code
that was kinked by loop optimization. */
- TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
- TIMEVAR (jump_time, thread_jumps (insns, max_reg_num (), 0));
+ timevar_push (TV_JUMP);
+ reg_scan (insns, max_reg_num (), 0);
+ thread_jumps (insns, max_reg_num (), 0);
+ timevar_pop (TV_JUMP);
}
- /* Dump rtl code after cse, if we are doing that. */
-
- if (cse2_dump)
- {
- close_dump_file (print_rtl, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".06.cse2", insns);
- }
+ close_dump_file (DFI_cse2, print_rtl, insns);
+ timevar_pop (TV_CSE2);
if (ggc_p)
ggc_collect ();
}
- if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
- {
- if (branch_prob_dump)
- open_dump_file (".07.bp", decl_printable_name (decl, 2));
-
- TIMEVAR
- (branch_prob_time,
- {
- branch_prob (insns, rtl_dump_file);
- });
+ cse_not_expected = 1;
- if (branch_prob_dump)
- {
- close_dump_file (print_rtl, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".07.bp", insns);
- }
+ regclass_init ();
- if (ggc_p)
- ggc_collect ();
- }
+
+ /* Do control and data flow analysis; wrote some of the results to
+ the dump file. */
- /* Now we choose between stupid (pcc-like) register allocation
- (if we got the -noreg switch and not -opt)
- and smart register allocation. */
+ timevar_push (TV_FLOW);
+ open_dump_file (DFI_cfg, decl);
- if (optimize > 0) /* Stupid allocation probably won't work */
- obey_regdecls = 0; /* if optimizations being done. */
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (insns);
- regclass_init ();
+ close_dump_file (DFI_cfg, print_rtl_with_bb, insns);
+
+ if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
+ {
+ timevar_push (TV_BRANCH_PROB);
+ open_dump_file (DFI_bp, decl);
- /* Print function header into flow dump now
- because doing the flow analysis makes some of the dump. */
+ branch_prob ();
- if (flow_dump)
- open_dump_file (".08.flow", decl_printable_name (decl, 2));
-
- if (obey_regdecls)
- {
- TIMEVAR (flow_time,
- {
- regclass (insns, max_reg_num ());
- stupid_life_analysis (insns, max_reg_num (),
- rtl_dump_file);
- });
+ close_dump_file (DFI_bp, print_rtl_with_bb, insns);
+ timevar_pop (TV_BRANCH_PROB);
}
- else
+
+ open_dump_file (DFI_life, decl);
+ if (optimize)
{
- /* Do control and data flow analysis,
- and write some of the results to dump file. */
+ struct loops loops;
- TIMEVAR
- (flow_time,
- {
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
- life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
- });
+ /* Discover and record the loop depth at the head of each basic
+ block. The loop infrastructure does the real job for us. */
+ flow_loops_find (&loops);
- if (warn_uninitialized || extra_warnings)
- {
- uninitialized_vars_warning (DECL_INITIAL (decl));
- if (extra_warnings)
- setjmp_args_warning ();
- }
- }
+ /* Estimate using heuristics if no profiling info is available. */
+ estimate_probability (&loops);
- /* Dump rtl after flow analysis. */
+ if (rtl_dump_file)
+ flow_loops_dump (&loops, rtl_dump_file, 0);
- if (flow_dump)
+ flow_loops_free (&loops);
+ }
+ life_analysis (insns, rtl_dump_file, PROP_FINAL);
+ mark_constant_function ();
+ timevar_pop (TV_FLOW);
+
+ if (warn_uninitialized || extra_warnings)
{
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".08.flow", insns);
+ uninitialized_vars_warning (DECL_INITIAL (decl));
+ if (extra_warnings)
+ setjmp_args_warning ();
}
+ close_dump_file (DFI_life, print_rtl_with_bb, insns);
+
if (ggc_p)
ggc_collect ();
- /* The first life analysis pass has finished. From now on we can not
- generate any new pseudos. */
- no_new_pseudos = 1;
-
/* If -opt, try combining insns through substitution. */
if (optimize > 0)
{
- TIMEVAR (combine_time, combine_instructions (insns, max_reg_num ()));
+ int rebuild_jump_labels_after_combine = 0;
- /* Dump rtl code after insn combination. */
+ timevar_push (TV_COMBINE);
+ open_dump_file (DFI_combine, decl);
- if (combine_dump)
+ rebuild_jump_labels_after_combine
+ = combine_instructions (insns, max_reg_num ());
+
+ /* Combining insns may have turned an indirect jump into a
+ direct jump. Rebuid the JUMP_LABEL fields of jumping
+ instructions. */
+ if (rebuild_jump_labels_after_combine)
{
- dump_rtl (".09.combine", decl, print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".09.combine", insns);
+ timevar_push (TV_JUMP);
+ rebuild_jump_labels (insns);
+ timevar_pop (TV_JUMP);
+
+ timevar_push (TV_FLOW);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (insns);
+
+ /* Blimey. We've got to have the CFG up to date for the call to
+ if_convert below. However, the random deletion of blocks
+ without updating life info can wind up with Wierd Stuff in
+ global_live_at_end. We then run sched1, which updates things
+ properly, discovers the wierdness and aborts. */
+ update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
+ PROP_DEATH_NOTES | PROP_KILL_DEAD_CODE
+ | PROP_SCAN_DEAD_CODE);
+
+ timevar_pop (TV_FLOW);
}
+ close_dump_file (DFI_combine, print_rtl_with_bb, insns);
+ timevar_pop (TV_COMBINE);
+
if (ggc_p)
ggc_collect ();
}
+ /* Rerun if-conversion, as combine may have simplified things enough to
+ now meet sequence length restrictions. */
+ if (optimize > 0)
+ {
+ timevar_push (TV_IFCVT);
+ open_dump_file (DFI_ce, decl);
+
+ if_convert (1);
+
+ close_dump_file (DFI_ce, print_rtl_with_bb, insns);
+ timevar_pop (TV_IFCVT);
+ }
+
/* Register allocation pre-pass, to reduce number of moves
necessary for two-address machines. */
if (optimize > 0 && (flag_regmove || flag_expensive_optimizations))
{
- if (regmove_dump)
- open_dump_file (".10.regmove", decl_printable_name (decl, 2));
+ timevar_push (TV_REGMOVE);
+ open_dump_file (DFI_regmove, decl);
- TIMEVAR (regmove_time, regmove_optimize (insns, max_reg_num (),
- rtl_dump_file));
+ regmove_optimize (insns, max_reg_num (), rtl_dump_file);
- if (regmove_dump)
- {
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".10.regmove", insns);
- }
+ close_dump_file (DFI_regmove, print_rtl_with_bb, insns);
+ timevar_pop (TV_REGMOVE);
if (ggc_p)
ggc_collect ();
}
- /* Print function header into sched dump now
- because doing the sched analysis makes some of the dump. */
+#ifdef OPTIMIZE_MODE_SWITCHING
+ if (optimize)
+ {
+ timevar_push (TV_GCSE);
+
+ if (optimize_mode_switching (NULL_PTR))
+ {
+ /* We did work, and so had to regenerate global life information.
+ Take advantage of this and don't re-recompute register life
+ information below. */
+ no_new_pseudos = 1;
+ }
+
+ timevar_pop (TV_GCSE);
+ }
+#endif
#ifdef INSN_SCHEDULING
+
+ /* Print function header into sched dump now
+ because doing the sched analysis makes some of the dump. */
if (optimize > 0 && flag_schedule_insns)
{
- if (sched_dump)
- open_dump_file (".11.sched", decl_printable_name (decl, 2));
+ timevar_push (TV_SCHED);
+ open_dump_file (DFI_sched, decl);
/* Do control and data sched analysis,
and write some of the results to dump file. */
- TIMEVAR (sched_time, schedule_insns (rtl_dump_file));
-
- /* Dump rtl after instruction scheduling. */
+ schedule_insns (rtl_dump_file);
- if (sched_dump)
- {
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".11.sched", insns);
- }
+ close_dump_file (DFI_sched, print_rtl_with_bb, insns);
+ timevar_pop (TV_SCHED);
if (ggc_p)
ggc_collect ();
+
+ /* Register lifetime information is up to date. From now on
+ we can not generate any new pseudos. */
+ no_new_pseudos = 1;
}
#endif
epilogue thus changing register elimination offsets. */
current_function_is_leaf = leaf_function_p ();
- /* Unless we did stupid register allocation,
- allocate pseudo-regs that are used only within 1 basic block.
+ timevar_push (TV_LOCAL_ALLOC);
+ open_dump_file (DFI_lreg, decl);
+
+ /* Allocate pseudo-regs that are used only within 1 basic block.
RUN_JUMP_AFTER_RELOAD records whether or not we need to rerun the
jump optimizer after register allocation and reloading are finished. */
- if (!obey_regdecls)
- TIMEVAR (local_alloc_time,
- {
- /* We recomputed reg usage as part of updating the rest
- of life info during sched. */
- if (! flag_schedule_insns)
- recompute_reg_usage (insns, ! optimize_size);
- regclass (insns, max_reg_num ());
- rebuild_label_notes_after_reload = local_alloc ();
- });
- else
- rebuild_label_notes_after_reload = 0;
+ if (! no_new_pseudos)
+ {
+ recompute_reg_usage (insns, ! optimize_size);
+
+ /* Register lifetime information is up to date. From now on
+ we can not generate any new pseudos. */
+ no_new_pseudos = 1;
+ }
+ regclass (insns, max_reg_num (), rtl_dump_file);
+ rebuild_label_notes_after_reload = local_alloc ();
- /* Dump rtl code after allocating regs within basic blocks. */
+ timevar_pop (TV_LOCAL_ALLOC);
- if (local_reg_dump)
+ if (dump_file[DFI_lreg].enabled)
{
- open_dump_file (".12.lreg", decl_printable_name (decl, 2));
+ timevar_push (TV_DUMP);
- TIMEVAR (dump_time, dump_flow_info (rtl_dump_file));
- TIMEVAR (dump_time, dump_local_alloc (rtl_dump_file));
+ dump_flow_info (rtl_dump_file);
+ dump_local_alloc (rtl_dump_file);
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".12.lreg", insns);
+ close_dump_file (DFI_lreg, print_rtl_with_bb, insns);
+ timevar_pop (TV_DUMP);
}
if (ggc_p)
ggc_collect ();
- if (global_reg_dump)
- open_dump_file (".13.greg", decl_printable_name (decl, 2));
+ timevar_push (TV_GLOBAL_ALLOC);
+ open_dump_file (DFI_greg, decl);
- /* Unless we did stupid register allocation,
- allocate remaining pseudo-regs, then do the reload pass
- fixing up any insns that are invalid. */
+ /* If optimizing, allocate remaining pseudo-regs. Do the reload
+ pass fixing up any insns that are invalid. */
- TIMEVAR (global_alloc_time,
- {
- if (!obey_regdecls)
- failure = global_alloc (rtl_dump_file);
- else
- failure = reload (insns, 0, rtl_dump_file);
- });
+ if (optimize)
+ failure = global_alloc (rtl_dump_file);
+ else
+ {
+ build_insn_chain (insns);
+ failure = reload (insns, 0, rtl_dump_file);
+ }
+ timevar_pop (TV_GLOBAL_ALLOC);
if (failure)
goto exit_rest_of_compilation;
/* Do a very simple CSE pass over just the hard registers. */
if (optimize > 0)
- reload_cse_regs (insns);
+ {
+ timevar_push (TV_RELOAD_CSE_REGS);
+ reload_cse_regs (insns);
+ timevar_pop (TV_RELOAD_CSE_REGS);
+ }
+
+ /* If optimizing, then go ahead and split insns now since we are about
+ to recompute flow information anyway. */
+ if (optimize > 0)
+ split_all_insns (0);
/* Register allocation and reloading may have turned an indirect jump into
a direct jump. If so, we must rebuild the JUMP_LABEL fields of
jumping instructions. */
if (rebuild_label_notes_after_reload)
- TIMEVAR (jump_time, rebuild_jump_labels (insns));
+ {
+ timevar_push (TV_JUMP);
- /* On some machines, the prologue and epilogue code, or parts thereof,
- can be represented as RTL. Doing so lets us schedule insns between
- it and the rest of the code and also allows delayed branch
- scheduling to operate in the epilogue. */
+ rebuild_jump_labels (insns);
- thread_prologue_and_epilogue_insns (insns);
+ timevar_pop (TV_JUMP);
+ }
- /* If optimizing and we are performing instruction scheduling after
- reload, then go ahead and split insns now since we are about to
- recompute flow information anyway.
+ if (dump_file[DFI_greg].enabled)
+ {
+ timevar_push (TV_DUMP);
- reload_cse_regs may expose more splitting opportunities, expecially
- for double-word operations. */
- if (optimize > 0 && flag_schedule_insns_after_reload)
- split_all_insns (0);
+ dump_global_regs (rtl_dump_file);
- if (global_reg_dump)
- {
- TIMEVAR (dump_time, dump_global_regs (rtl_dump_file));
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".13.greg", insns);
+ close_dump_file (DFI_greg, print_rtl_with_bb, insns);
+ timevar_pop (TV_DUMP);
}
/* Re-create the death notes which were deleted during reload. */
- if (flow2_dump)
- open_dump_file (".14.flow2", decl_printable_name (decl, 2));
-
+ timevar_push (TV_FLOW2);
+ open_dump_file (DFI_flow2, decl);
+
+ jump_optimize (insns, !JUMP_CROSS_JUMP,
+ !JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+
+ /* On some machines, the prologue and epilogue code, or parts thereof,
+ can be represented as RTL. Doing so lets us schedule insns between
+ it and the rest of the code and also allows delayed branch
+ scheduling to operate in the epilogue. */
+ thread_prologue_and_epilogue_insns (insns);
+
if (optimize)
{
- TIMEVAR
- (flow2_time,
- {
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
- life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
- });
+ cleanup_cfg (insns);
+ life_analysis (insns, rtl_dump_file, PROP_FINAL);
+
+ /* This is kind of a heuristic. We need to run combine_stack_adjustments
+ even for machines with possibly nonzero RETURN_POPS_ARGS
+ and ACCUMULATE_OUTGOING_ARGS. We expect that only ports having
+ push instructions will have popping returns. */
+#ifndef PUSH_ROUNDING
+ if (!ACCUMULATE_OUTGOING_ARGS)
+#endif
+ combine_stack_adjustments ();
if (ggc_p)
ggc_collect ();
flow2_completed = 1;
- if (flow2_dump)
+ close_dump_file (DFI_flow2, print_rtl_with_bb, insns);
+ timevar_pop (TV_FLOW2);
+
+ if (optimize > 0)
{
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".14.flow2", insns);
+ timevar_push (TV_IFCVT2);
+ open_dump_file (DFI_ce2, decl);
+
+ if_convert (1);
+
+ close_dump_file (DFI_ce2, print_rtl_with_bb, insns);
+ timevar_pop (TV_IFCVT2);
}
#ifdef HAVE_peephole2
if (optimize > 0 && flag_peephole2)
{
- if (peephole2_dump)
- open_dump_file (".15.peephole2", decl_printable_name (decl, 2));
+ timevar_push (TV_PEEPHOLE2);
+ open_dump_file (DFI_peephole2, decl);
- TIMEVAR (peephole2_time, peephole2_optimize (rtl_dump_file));
+ peephole2_optimize (rtl_dump_file);
- if (peephole2_dump)
- {
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".15.peephole2", insns);
- }
+ close_dump_file (DFI_peephole2, print_rtl_with_bb, insns);
+ timevar_pop (TV_PEEPHOLE2);
}
#endif
+ if (optimize > 0 && flag_rename_registers)
+ {
+ timevar_push (TV_RENAME_REGISTERS);
+ open_dump_file (DFI_rnreg, decl);
+
+ regrename_optimize ();
+
+ close_dump_file (DFI_rnreg, print_rtl_with_bb, insns);
+ timevar_pop (TV_RENAME_REGISTERS);
+ }
+
#ifdef INSN_SCHEDULING
if (optimize > 0 && flag_schedule_insns_after_reload)
{
- if (sched2_dump)
- open_dump_file (".16.sched2", decl_printable_name (decl, 2));
+ timevar_push (TV_SCHED2);
+ open_dump_file (DFI_sched2, decl);
/* Do control and data sched analysis again,
and write some more of the results to dump file. */
- TIMEVAR (sched2_time, schedule_insns (rtl_dump_file));
-
- /* Dump rtl after post-reorder instruction scheduling. */
+ schedule_insns (rtl_dump_file);
- if (sched2_dump)
- {
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".16.sched2", insns);
- }
+ close_dump_file (DFI_sched2, print_rtl_with_bb, insns);
+ timevar_pop (TV_SCHED2);
if (ggc_p)
ggc_collect ();
= optimize > 0 && only_leaf_regs_used () && leaf_function_p ();
#endif
- /* One more attempt to remove jumps to .+1
- left by dead-store-elimination.
- Also do cross-jumping this time
- and delete no-op move insns. */
+ if (optimize > 0 && flag_reorder_blocks)
+ {
+ timevar_push (TV_REORDER_BLOCKS);
+ open_dump_file (DFI_bbro, decl);
+
+ reorder_basic_blocks ();
+
+ close_dump_file (DFI_bbro, print_rtl_with_bb, insns);
+ timevar_pop (TV_REORDER_BLOCKS);
+ }
+
+ /* One more attempt to remove jumps to .+1 left by dead-store elimination.
+ Also do cross-jumping this time and delete no-op move insns. */
if (optimize > 0)
{
- TIMEVAR (jump_time, jump_optimize (insns, JUMP_CROSS_JUMP,
- JUMP_NOOP_MOVES,
- !JUMP_AFTER_REGSCAN));
+ timevar_push (TV_JUMP);
+ open_dump_file (DFI_jump2, decl);
- /* Dump rtl code after jump, if we are doing that. */
+ jump_optimize (insns, JUMP_CROSS_JUMP, JUMP_NOOP_MOVES,
+ !JUMP_AFTER_REGSCAN);
- if (jump2_opt_dump)
- {
- dump_rtl (".17.jump2", decl, print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".17.jump2", insns);
- }
+ /* CFG no longer kept up to date. */
+
+ close_dump_file (DFI_jump2, print_rtl_with_bb, insns);
+ timevar_pop (TV_JUMP);
}
/* If a machine dependent reorganization is needed, call it. */
#ifdef MACHINE_DEPENDENT_REORG
- if (mach_dep_reorg_dump)
- open_dump_file (".18.mach", decl_printable_name (decl, 2));
+ open_dump_file (DFI_mach, decl);
- MACHINE_DEPENDENT_REORG (insns);
+ MACHINE_DEPENDENT_REORG (insns);
- if (mach_dep_reorg_dump)
- {
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".18.mach", insns);
- }
+ close_dump_file (DFI_mach, print_rtl_with_bb, insns);
- if (ggc_p)
- ggc_collect ();
+ if (ggc_p)
+ ggc_collect ();
#endif
/* If a scheduling pass for delayed branches is to be done,
#ifdef DELAY_SLOTS
if (optimize > 0 && flag_delayed_branch)
{
- if (dbr_sched_dump)
- open_dump_file (".19.dbr", decl_printable_name (decl, 2));
+ timevar_push (TV_DBR_SCHED);
+ open_dump_file (DFI_dbr, decl);
- TIMEVAR
- (dbr_sched_time,
- {
- dbr_schedule (insns, rtl_dump_file);
- });
+ dbr_schedule (insns, rtl_dump_file);
- if (dbr_sched_dump)
- {
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".19.dbr", insns);
- }
- }
+ close_dump_file (DFI_dbr, print_rtl_with_bb, insns);
+ timevar_pop (TV_DBR_SCHED);
- if (ggc_p)
- ggc_collect ();
+ if (ggc_p)
+ ggc_collect ();
+ }
#endif
- /* Shorten branches. */
- TIMEVAR (shorten_branch_time,
- {
- shorten_branches (get_insns ());
- });
+ /* Shorten branches.
+
+ Note this must run before reg-stack because of death note (ab)use
+ in the ia32 backend. */
+ timevar_push (TV_SHORTEN_BRANCH);
+ shorten_branches (get_insns ());
+ timevar_pop (TV_SHORTEN_BRANCH);
#ifdef STACK_REGS
- if (stack_reg_dump)
- open_dump_file (".20.stack", decl_printable_name (decl, 2));
+ timevar_push (TV_REG_STACK);
+ open_dump_file (DFI_stack, decl);
- TIMEVAR (stack_reg_time, reg_to_stack (insns, rtl_dump_file));
+ reg_to_stack (insns, rtl_dump_file);
- if (stack_reg_dump)
- {
- close_dump_file (print_rtl_with_bb, insns);
- if (graph_dump_format != no_graph)
- print_rtl_graph_with_bb (dump_base_name, ".20.stack", insns);
- }
+ close_dump_file (DFI_stack, print_rtl_with_bb, insns);
+ timevar_pop (TV_REG_STACK);
- if (ggc_p)
- ggc_collect ();
+ if (ggc_p)
+ ggc_collect ();
#endif
+ current_function_nothrow = nothrow_function_p ();
+ if (current_function_nothrow)
+ /* Now we know that this can't throw; set the flag for the benefit
+ of other functions later in this translation unit. */
+ TREE_NOTHROW (current_function_decl) = 1;
+
/* Now turn the rtl into assembler code. */
- TIMEVAR (final_time,
- {
- rtx x;
- char *fnname;
-
- /* Get the function's name, as described by its RTL.
- This may be different from the DECL_NAME name used
- in the source file. */
-
- x = DECL_RTL (decl);
- if (GET_CODE (x) != MEM)
- abort ();
- x = XEXP (x, 0);
- if (GET_CODE (x) != SYMBOL_REF)
- abort ();
- fnname = XSTR (x, 0);
-
- assemble_start_function (decl, fnname);
- final_start_function (insns, asm_out_file, optimize);
- final (insns, asm_out_file, optimize, 0);
- final_end_function (insns, asm_out_file, optimize);
- assemble_end_function (decl, fnname);
- if (! quiet_flag)
- fflush (asm_out_file);
+ timevar_push (TV_FINAL);
+ {
+ rtx x;
+ const char *fnname;
+
+ /* Get the function's name, as described by its RTL. This may be
+ different from the DECL_NAME name used in the source file. */
+
+ x = DECL_RTL (decl);
+ if (GET_CODE (x) != MEM)
+ abort ();
+ x = XEXP (x, 0);
+ if (GET_CODE (x) != SYMBOL_REF)
+ abort ();
+ fnname = XSTR (x, 0);
+
+ assemble_start_function (decl, fnname);
+ final_start_function (insns, asm_out_file, optimize);
+ final (insns, asm_out_file, optimize, 0);
+ final_end_function (insns, asm_out_file, optimize);
+ assemble_end_function (decl, fnname);
+ if (! quiet_flag)
+ fflush (asm_out_file);
/* Release all memory allocated by flow. */
- free_basic_block_vars (0);
+ free_basic_block_vars (0);
- /* Release all memory held by regsets now */
- regset_release_memory ();
- });
+ /* Release all memory held by regsets now */
+ regset_release_memory ();
+ }
+ timevar_pop (TV_FINAL);
- if (ggc_p)
- ggc_collect ();
+ if (ggc_p)
+ ggc_collect ();
/* Write DBX symbols if requested */
for those inline functions that need to have out-of-line copies
generated. During that call, we *will* be routed past here. */
+ timevar_push (TV_SYMOUT);
#ifdef DBX_DEBUGGING_INFO
if (write_symbols == DBX_DEBUG)
- TIMEVAR (symout_time, dbxout_function (decl));
+ dbxout_function (decl);
#endif
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
- TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 0));
+ dwarfout_file_scope_decl (decl, 0);
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
- TIMEVAR (symout_time, dwarf2out_decl (decl));
+ dwarf2out_decl (decl);
#endif
+ timevar_pop (TV_SYMOUT);
exit_rest_of_compilation:
- free_bb_mem ();
-
/* In case the function was not output,
don't leave any temporary anonymous types
queued up for sdb output. */
sdbout_types (NULL_TREE);
#endif
- /* Put back the tree of subblocks and list of arguments
- from before we copied them.
- Code generation and the output of debugging info may have modified
- the copy, but the original is unchanged. */
-
- if (saved_block_tree != 0)
- {
- DECL_INITIAL (decl) = saved_block_tree;
- DECL_ARGUMENTS (decl) = saved_arguments;
- DECL_ABSTRACT_ORIGIN (decl) = NULL_TREE;
- }
-
reload_completed = 0;
flow2_completed = 0;
no_new_pseudos = 0;
- TIMEVAR (final_time,
- {
- /* Clear out the insn_length contents now that they are no
- longer valid. */
- init_insn_lengths ();
+ timevar_push (TV_FINAL);
- /* Clear out the real_constant_chain before some of the rtx's
+ /* Clear out the insn_length contents now that they are no
+ longer valid. */
+ init_insn_lengths ();
+
+ /* Clear out the real_constant_chain before some of the rtx's
it runs through become garbage. */
- clear_const_double_mem ();
+ clear_const_double_mem ();
+
+ /* Cancel the effect of rtl_in_current_obstack. */
+ resume_temporary_allocation ();
- /* Cancel the effect of rtl_in_current_obstack. */
- resume_temporary_allocation ();
+ /* Show no temporary slots allocated. */
+ init_temp_slots ();
- /* Show no temporary slots allocated. */
- init_temp_slots ();
+ free_basic_block_vars (0);
- free_basic_block_vars (0);
- });
+ timevar_pop (TV_FINAL);
/* Make sure volatile mem refs aren't considered valid operands for
arithmetic insns. We must call this here if this is a nested inline
init_recog_no_volatile ();
/* We're done with this function. Free up memory if we can. */
- free_after_parsing (current_function);
+ free_after_parsing (cfun);
if (! DECL_DEFER_OUTPUT (decl))
- free_after_compilation (current_function);
- current_function = 0;
+ free_after_compilation (cfun);
+ cfun = 0;
if (ggc_p)
ggc_collect ();
- /* The parsing time is all the time spent in yyparse
- *except* what is spent in this function. */
-
- parse_time -= get_run_time () - start_time;
+ timevar_pop (TV_REST_OF_COMPILATION);
}
\f
static void
W_options[i].string, description);
}
+ printf (" -Wunused Enable unused warnings\n");
printf (" -Wid-clash-<num> Warn if 2 identifiers have the same first <num> chars\n");
printf (" -Wlarger-than-<number> Warn if an object is larger than <number> bytes\n");
printf (" -p Enable function profiling\n");
printf (" -d[letters] Enable dumps from specific passes of the compiler\n");
printf (" -dumpbase <file> Base name to be used for dumps from specific passes\n");
#if defined INSN_SCHEDULING
- printf (" -sched-verbose=<number> Set the verbosity level of the scheduler\n");
+ printf (" -fsched-verbose=<number> Set the verbosity level of the scheduler\n");
#endif
printf (" --help Display this information\n");
decode_d_option (arg)
const char * arg;
{
- while (* arg)
- switch (* arg ++)
+ int i, c, matched;
+
+ while (*arg)
+ switch (c = *arg++)
{
case 'a':
- branch_prob_dump = 1;
- combine_dump = 1;
-#ifdef DELAY_SLOTS
- dbr_sched_dump = 1;
-#endif
- flow_dump = 1;
- flow2_dump = 1;
- global_reg_dump = 1;
- jump_opt_dump = 1;
- addressof_dump = 1;
- jump2_opt_dump = 1;
- local_reg_dump = 1;
- loop_dump = 1;
- regmove_dump = 1;
- rtl_dump = 1;
- cse_dump = 1;
- cse2_dump = 1;
- gcse_dump = 1;
- sched_dump = 1;
- sched2_dump = 1;
-#ifdef STACK_REGS
- stack_reg_dump = 1;
-#endif
-#ifdef MACHINE_DEPENDENT_REORG
- mach_dep_reorg_dump = 1;
-#endif
- peephole2_dump = 1;
+ for (i = 0; i < DFI_MAX; ++i)
+ dump_file[i].enabled = 1;
break;
case 'A':
flag_debug_asm = 1;
break;
- case 'b':
- branch_prob_dump = 1;
- break;
- case 'c':
- combine_dump = 1;
- break;
-#ifdef DELAY_SLOTS
- case 'd':
- dbr_sched_dump = 1;
- break;
-#endif
- case 'f':
- flow_dump = 1;
- break;
- case 'F':
- addressof_dump = 1;
- break;
- case 'g':
- global_reg_dump = 1;
- break;
- case 'G':
- gcse_dump = 1;
- break;
- case 'j':
- jump_opt_dump = 1;
- break;
- case 'J':
- jump2_opt_dump = 1;
- break;
-#ifdef STACK_REGS
- case 'k':
- stack_reg_dump = 1;
- break;
-#endif
- case 'l':
- local_reg_dump = 1;
- break;
- case 'L':
- loop_dump = 1;
- break;
case 'm':
flag_print_mem = 1;
break;
-#ifdef MACHINE_DEPENDENT_REORG
- case 'M':
- mach_dep_reorg_dump = 1;
- break;
-#endif
case 'p':
flag_print_asm_name = 1;
break;
- case 'r':
- rtl_dump = 1;
- break;
- case 'R':
- sched2_dump = 1;
- break;
- case 's':
- cse_dump = 1;
- break;
- case 'S':
- sched_dump = 1;
- break;
- case 't':
- cse2_dump = 1;
- break;
- case 'N':
- regmove_dump = 1;
- break;
case 'v':
graph_dump_format = vcg;
break;
- case 'w':
- flow2_dump = 1;
- break;
case 'x':
rtl_dump_and_exit = 1;
break;
case 'y':
set_yydebug (1);
break;
- case 'z':
- peephole2_dump = 1;
- break;
case 'D': /* These are handled by the preprocessor. */
case 'I':
break;
+
default:
- warning ("unrecognised gcc debugging option: %c", arg[-1]);
+ matched = 0;
+ for (i = 0; i < DFI_MAX; ++i)
+ if (c == dump_file[i].debug_switch)
+ {
+ dump_file[i].enabled = 1;
+ matched = 1;
+ }
+
+ if (! matched)
+ warning ("unrecognized gcc debugging option: %c", c);
break;
}
}
else if (!strncmp (arg, "align-loops=", 12))
align_loops = read_integral_parameter (arg + 12, arg - 2, align_loops);
else if (!strncmp (arg, "align-functions=", 16))
- align_functions =
- read_integral_parameter (arg + 16, arg - 2, align_functions);
+ align_functions
+ = read_integral_parameter (arg + 16, arg - 2, align_functions);
else if (!strncmp (arg, "align-jumps=", 12))
align_jumps = read_integral_parameter (arg + 12, arg - 2, align_jumps);
else if (!strncmp (arg, "align-labels=", 13))
align_labels = read_integral_parameter (arg + 13, arg - 2, align_labels);
+ else if (!strncmp (arg, "stack-limit-register=", 21))
+ {
+ int reg = decode_reg_name (arg + 21);
+ if (reg < 0)
+ error ("unrecognized register name `%s'", arg + 21);
+ else
+ stack_limit_rtx = gen_rtx_REG (Pmode, reg);
+ }
+ else if (!strncmp (arg, "stack-limit-symbol=", 19))
+ {
+ char *nm;
+ if (ggc_p)
+ nm = ggc_alloc_string (arg + 19, strlen (arg + 19));
+ else
+ nm = xstrdup (arg + 19);
+ stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, nm);
+ }
+ else if (!strcmp (arg, "no-stack-limit"))
+ stack_limit_rtx = NULL_RTX;
else if (!strcmp (arg, "preprocessed"))
/* Recognise this switch but do nothing. This prevents warnings
- about an unrecognised switch if cpplib has not been linked in. */
+ about an unrecognized switch if cpplib has not been linked in. */
;
else
return 0;
/* Parse a -W... comand line switch. ARG is the value after the -W.
It is safe to access 'ARG - 2' to generate the full switch name.
Return the number of strings consumed. */
+
static int
decode_W_option (arg)
const char * arg;
if (!strncmp (arg, "id-clash-", 9))
{
- const int id_clash_val = read_integral_parameter (arg + 9, arg - 2, -1);
+ id_clash_len = read_integral_parameter (arg + 9, arg - 2, -1);
- if (id_clash_val != -1)
- {
- id_clash_len = id_clash_val;
- warn_id_clash = 1;
- }
+ if (id_clash_len != -1)
+ warn_id_clash = 1;
}
else if (!strncmp (arg, "larger-than-", 12))
{
- const int larger_than_val =
- read_integral_parameter (arg + 12, arg - 2, -1);
- if (larger_than_val != -1)
- {
- larger_than_size = larger_than_val;
- warn_larger_than = 1;
- }
+ larger_than_size = read_integral_parameter (arg + 12, arg - 2, -1);
+
+ if (larger_than_size != -1)
+ warn_larger_than = 1;
+ }
+ else if (!strcmp (arg, "unused"))
+ {
+ set_Wunused (1);
+ }
+ else if (!strcmp (arg, "no-unused"))
+ {
+ set_Wunused (0);
}
else
return 0;
number of strings that have already been decoded in a language
specific fashion before this function was invoked. */
-static unsigned
+static unsigned int
independent_decode_option (argc, argv, strings_processed)
int argc;
- char ** argv;
- unsigned strings_processed ATTRIBUTE_UNUSED;
+ char **argv;
+ unsigned int strings_processed;
{
- char * arg = argv[0];
+ char *arg = argv[0];
if (arg[0] != '-' || arg[1] == 0)
{
if (* arg == 'Y')
arg ++;
- switch (* arg)
+ switch (*arg)
{
default:
return 0;
return decode_f_option (arg + 1);
case 'g':
- return decode_g_option (arg + 1);
+ if (strings_processed == 0)
+ return decode_g_option (arg + 1);
+ else
+ return strings_processed;
case 'd':
if (!strcmp (arg, "dumpbase"))
Exit code is 35 if can't open files, 34 if fatal error,
33 if had nonfatal errors, else success. */
-extern int main PROTO ((int, char **));
+extern int main PARAMS ((int, char **));
int
main (argc, argv)
save_argv = argv;
p = argv[0] + strlen (argv[0]);
- while (p != argv[0] && p[-1] != '/'
-#ifdef DIR_SEPARATOR
- && p[-1] != DIR_SEPARATOR
-#endif
- )
+ while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
--p;
progname = p;
-#if defined (RLIMIT_STACK) && defined (HAVE_GETRLIMIT) && defined (HAVE_SETRLIMIT)
- /* Get rid of any avoidable limit on stack size. */
- {
- struct rlimit rlim;
-
- /* Set the stack limit huge so that alloca does not fail. */
- getrlimit (RLIMIT_STACK, &rlim);
- rlim.rlim_cur = rlim.rlim_max;
- setrlimit (RLIMIT_STACK, &rlim);
- }
-#endif
-
#ifdef HAVE_LC_MESSAGES
setlocale (LC_MESSAGES, "");
#endif
/* Initialize the garbage-collector. */
init_ggc ();
ggc_add_root (&input_file_stack, 1, sizeof input_file_stack,
- &mark_file_stack);
+ mark_file_stack);
+ ggc_add_rtx_root (&stack_limit_rtx, 1);
+ ggc_add_tree_root (¤t_function_decl, 1);
+ ggc_add_tree_root (¤t_function_func_begin_label, 1);
/* Perform language-specific options intialization. */
lang_init_options ();
}
}
- obey_regdecls = (optimize == 0);
-
if (optimize >= 1)
{
flag_defer_pop = 1;
if (optimize >= 2)
{
+ flag_optimize_sibling_calls = 1;
flag_cse_follow_jumps = 1;
flag_cse_skip_blocks = 1;
flag_gcse = 1;
/* Perform normal command line switch decoding. */
for (i = 1; i < argc;)
{
- unsigned lang_processed;
- unsigned indep_processed;
+ unsigned int lang_processed;
+ unsigned int indep_processed;
/* Give the language a chance to decode the option for itself. */
lang_processed = lang_decode_option (argc - i, argv + i);
/* Now see if the option also has a language independent meaning.
Some options are both language specific and language independent,
eg --help. It is possible that there might be options that should
- only be decoded in a language independent way if the were not
+ only be decoded in a language independent way if they were not
decoded in a langauge specific way, which is why 'lang_processed'
is passed in. */
indep_processed = independent_decode_option (argc - i, argv + i,
break;
}
- if (option)
+ if (j != NUM_ELEM (documented_lang_options))
{
if (extra_warnings)
{
}
}
else
- error ("Unrecognised option `%s'", argv[i]);
+ error ("Unrecognized option `%s'", argv[i]);
i++;
}
#ifdef DWARF2_UNWIND_INFO
exceptions_via_longjmp = ! DWARF2_UNWIND_INFO;
#else
+#ifdef IA64_UNWIND_INFO
+ exceptions_via_longjmp = ! IA64_UNWIND_INFO;
+#else
exceptions_via_longjmp = 1;
#endif
+#endif
}
+ /* Since each function gets its own handler data, we can't support the
+ new model currently, since it depend on a specific rethrow label
+ which is declared at the front of the table, and we can only
+ have one such symbol in a file. */
+#ifdef IA64_UNWIND_INFO
+ flag_new_exceptions = 0;
+#endif
+
/* Set up the align_*_log variables, defaulting them to 1 if they
were still unset. */
if (align_loops <= 0) align_loops = 1;
{
char *lim = (char *) sbrk (0);
- notice ("Data size %ld.\n", (long) (lim - (char *) &environ));
+ fnotice (stderr, "Data size %ld.\n", (long) (lim - (char *) &environ));
fflush (stderr);
#ifndef __MSDOS__
void
debug_start_source_file (filename)
- register char *filename ATTRIBUTE_UNUSED;
+ register const char *filename ATTRIBUTE_UNUSED;
{
#ifdef DBX_DEBUGGING_INFO
if (write_symbols == DBX_DEBUG)
dwarf2out_undef (lineno, buffer);
#endif /* DWARF2_DEBUGGING_INFO */
}
+
+/* Returns nonzero if it is appropriate not to emit any debugging
+ information for BLOCK, because it doesn't contain any instructions.
+ This may not be the case for blocks containing nested functions, since
+ we may actually call such a function even though the BLOCK information
+ is messed up. */
+
+int
+debug_ignore_block (block)
+ tree block ATTRIBUTE_UNUSED;
+{
+ /* Never delete the BLOCK for the outermost scope
+ of the function; we can refer to names from
+ that scope even if the block notes are messed up. */
+ if (is_body_block (block))
+ return 0;
+
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ return dwarf2out_ignore_block (block);
+#endif
+
+ return 1;
+}