/* Top level of GNU C compiler
- Copyright (C) 1987, 88, 89, 92-6, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-7, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
#else
#include <varargs.h>
#endif
-#include <stdio.h>
+#undef FLOAT /* This is for hpux. They should change hpux. */
+#undef FFS /* Some systems define this in param.h. */
+#include "system.h"
#include <signal.h>
#include <setjmp.h>
-#include <sys/types.h>
-#include <ctype.h>
#include <sys/stat.h>
-#ifndef _WIN32
-#ifdef USG
-#undef FLOAT
-#include <sys/param.h>
-/* This is for hpux. It is a real screw. They should change hpux. */
-#undef FLOAT
-#include <sys/times.h>
-#include <time.h> /* Correct for hpux at least. Is it good on other USG? */
-#undef FFS /* Some systems define this in param.h. */
-#else
-#ifndef VMS
-#include <sys/time.h>
-#include <sys/resource.h>
-#endif
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
#endif
+
+#ifdef HAVE_SYS_TIMES_H
+# include <sys/times.h>
#endif
#include "input.h"
#include "rtl.h"
#include "flags.h"
#include "insn-attr.h"
+#include "insn-codes.h"
+#include "insn-config.h"
+#include "recog.h"
#include "defaults.h"
#include "output.h"
-#include "bytecode.h"
-#include "bc-emit.h"
#include "except.h"
#ifdef XCOFF_DEBUGGING_INFO
extern void dump_local_alloc ();
extern void regset_release_memory ();
+extern void print_rtl ();
+extern void print_rtl_with_bb ();
+
void rest_of_decl_compilation ();
void error_with_file_and_line PVPROTO((char *file, int line, char *s, ...));
void error_with_decl PVPROTO((tree decl, char *s, ...));
void sorry PVPROTO((char *s, ...));
void really_sorry PVPROTO((char *s, ...));
void fancy_abort ();
-#ifndef abort
-void abort ();
-#endif
void set_target_switch ();
static char *decl_name ();
/* Length of line when printing switch values. */
#define MAX_LINE 75
-#ifdef __alpha
+#ifdef NEED_DECLARATION_ABORT
+void abort ();
+#endif
+
+#ifdef NEED_DECLARATION_SBRK
extern char *sbrk ();
#endif
char *main_input_filename;
+#if !USE_CPPLIB
/* Stream for reading from the input file. */
-
FILE *finput;
+#endif
/* Current line number in real source file. */
int rtl_dump = 0;
int rtl_dump_and_exit = 0;
int jump_opt_dump = 0;
+int addressof_dump = 0;
int cse_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 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
/* Name for output file of assembly code, specified with -o. */
int optimize = 0;
+/* Nonzero means optimize for size. -Os.
+ The only valid values are zero and non-zero. When optimize_size is
+ non-zero, optimize defaults to 2, but certain individual code
+ bloating optimizations are disabled. */
+
+int optimize_size = 0;
+
/* Number of error messages and warning messages so far. */
int errorcount = 0;
int warningcount = 0;
int sorrycount = 0;
-/* Flag to output bytecode instead of native assembler */
-int output_bytecode = 0;
-
/* 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:
int flag_unroll_all_loops;
+/* Nonzero forces all invariant computations in loops to be moved
+ outside the loop. */
+
+int flag_move_all_movables = 0;
+
+/* Nonzero forces all general induction variables in loops to be
+ strength reduced. */
+
+int flag_reduce_all_givs = 0;
+
/* Nonzero for -fwritable-strings:
store string constants in data segment and don't uniquize them. */
static int flag_rerun_cse_after_loop;
+/* Nonzero means to run loop optimizations twice. */
+
+int flag_rerun_loop_opt;
+
/* Nonzero for -finline-functions: ok to inline functions that look like
good inline candidates. */
/* Nonzero means generate extra code for exception handling and enable
exception handling. */
-int flag_exceptions = 1;
+int flag_exceptions = 2;
/* Nonzero means don't place uninitialized global data in common storage
by default. */
int flag_schedule_insns = 0;
int flag_schedule_insns_after_reload = 0;
+#ifdef HAIFA
+/* The following flags have effect only for scheduling before register
+ allocation:
+
+ flag_schedule_interblock means schedule insns accross basic blocks.
+ flag_schedule_speculative means allow speculative motion of non-load insns.
+ flag_schedule_speculative_load means allow speculative motion of some
+ load insns.
+ flag_schedule_speculative_load_dangerous allows speculative motion of more
+ load insns. */
+
+int flag_schedule_interblock = 1;
+int flag_schedule_speculative = 1;
+int flag_schedule_speculative_load = 0;
+int flag_schedule_speculative_load_dangerous = 0;
+
+/* flag_on_branch_count_reg means try to replace add-1,compare,branch tupple
+ by a cheaper branch, on a count register. */
+int flag_branch_on_count_reg;
+#endif /* HAIFA */
+
+
/* -finhibit-size-directive inhibits output of .size for ELF.
This is used only for compiling crtstuff.c,
and it may be extended to other effects
the generated assembly code (to make it more readable). This option
is generally only of use to those who actually need to read the
generated assembly code (perhaps while debugging the compiler itself).
- -fverbose-asm is the default. -fno-verbose-asm causes the extra information
+ -fno-verbose-asm, the default, causes the extra information
to be omitted and is useful when comparing two assembler files. */
-int flag_verbose_asm = 1;
+int flag_verbose_asm = 0;
/* -dA causes debug commentary information to be produced in
the generated assembly code (to make it more readable). This option
to be allocated dynamically. */
int flag_stack_check;
+/* -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. */
+int flag_check_memory_usage = 0;
+
+/* -fprefix-function-name causes function name to be prefixed. This
+ can be used with -fcheck-memory-usage to isolate code compiled with
+ -fcheck-memory-usage. */
+int flag_prefix_function_name = 0;
+
+int flag_regmove = 0;
+
+/* 0 if pointer arguments may alias each other. True in C.
+ 1 if pointer arguments may not alias each other but may alias
+ global variables.
+ 2 if pointer arguments may not alias each other and may not
+ alias global variables. True in Fortran.
+ This defaults to 0 for C. */
+int flag_argument_noalias = 0;
+
/* Table of language-independent -f options.
STRING is the option name. VARIABLE is the address of the variable.
ON_VALUE is the value to store in VARIABLE
{"strength-reduce", &flag_strength_reduce, 1},
{"unroll-loops", &flag_unroll_loops, 1},
{"unroll-all-loops", &flag_unroll_all_loops, 1},
+ {"move-all-movables", &flag_move_all_movables, 1},
+ {"reduce-all-givs", &flag_reduce_all_givs, 1},
{"writable-strings", &flag_writable_strings, 1},
{"peephole", &flag_no_peephole, 0},
{"force-mem", &flag_force_mem, 1},
{"reg-struct-return", &flag_pcc_struct_return, 0},
{"delayed-branch", &flag_delayed_branch, 1},
{"rerun-cse-after-loop", &flag_rerun_cse_after_loop, 1},
+ {"rerun-loop-opt", &flag_rerun_loop_opt, 1},
{"pretend-float", &flag_pretend_float, 1},
{"schedule-insns", &flag_schedule_insns, 1},
{"schedule-insns2", &flag_schedule_insns_after_reload, 1},
+#ifdef HAIFA
+ {"sched-interblock",&flag_schedule_interblock, 1},
+ {"sched-spec",&flag_schedule_speculative, 1},
+ {"sched-spec-load",&flag_schedule_speculative_load, 1},
+ {"sched-spec-load-dangerous",&flag_schedule_speculative_load_dangerous, 1},
+ {"branch-count-reg",&flag_branch_on_count_reg, 1},
+#endif /* HAIFA */
{"pic", &flag_pic, 1},
{"PIC", &flag_pic, 2},
{"exceptions", &flag_exceptions, 1},
{"function-sections", &flag_function_sections, 1},
{"verbose-asm", &flag_verbose_asm, 1},
{"gnu-linker", &flag_gnu_linker, 1},
+ {"regmove", &flag_regmove, 1},
{"pack-struct", &flag_pack_struct, 1},
{"stack-check", &flag_stack_check, 1},
- {"bytecode", &output_bytecode, 1}
+ {"argument-alias", &flag_argument_noalias, 0},
+ {"argument-noalias", &flag_argument_noalias, 1},
+ {"argument-noalias-global", &flag_argument_noalias, 2},
+ {"check-memory-usage", &flag_check_memory_usage, 1},
+ {"prefix-function-name", &flag_prefix_function_name, 1}
};
/* Table of language-specific options. */
"-Wno-format",
"-Wimport",
"-Wno-import",
+ "-Wimplicit-function-declaration",
+ "-Wno-implicit-function-declaration",
+ "-Werror-implicit-function-declaration",
+ "-Wimplicit-int",
+ "-Wno-implicit-int",
"-Wimplicit",
"-Wno-implicit",
"-Wmain",
"-Wno-redundant-decls",
"-Wsign-compare",
"-Wno-sign-compare",
+ "-Wunknown-pragmas",
+ "-Wno-unknown-pragmas",
"-Wstrict-prototypes",
"-Wno-strict-prototypes",
"-Wtraditional",
"-Wno-selector",
"-Wprotocol",
"-Wno-protocol",
+ "-print-objc-runtime-info",
#include "options.h"
0
FILE *asm_out_file;
FILE *aux_info_file;
-FILE *rtl_dump_file;
-FILE *jump_opt_dump_file;
-FILE *cse_dump_file;
-FILE *loop_dump_file;
-FILE *cse2_dump_file;
-FILE *branch_prob_dump_file;
-FILE *flow_dump_file;
-FILE *combine_dump_file;
-FILE *sched_dump_file;
-FILE *local_reg_dump_file;
-FILE *global_reg_dump_file;
-FILE *sched2_dump_file;
-FILE *jump2_opt_dump_file;
-FILE *dbr_sched_dump_file;
-FILE *stack_reg_dump_file;
+FILE *rtl_dump_file = NULL;
/* Time accumulators, to count the total time spent in various passes. */
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 sched2_time;
+#ifdef DELAY_SLOTS
int dbr_sched_time;
+#endif
int shorten_branch_time;
int stack_reg_time;
int final_time;
int
get_run_time ()
{
-#ifndef _WIN32
-#ifdef USG
- struct tms tms;
-#else
-#ifndef VMS
- struct rusage rusage;
-#else
- struct
- {
- int proc_user_time;
- int proc_system_time;
- int child_user_time;
- int child_system_time;
- } vms_times;
-#endif
-#endif
-#endif
-
if (quiet_flag)
return 0;
-#ifdef _WIN32
+
+#ifdef __BEOS__
+ return 0;
+#else /* not BeOS */
+#if defined (_WIN32) && !defined (__CYGWIN32__)
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
- times (&tms);
- return (tms.tms_utime + tms.tms_stime) * (1000000 / HZ);
+ {
+ 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
- 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);
+ {
+ 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 */
- times (&vms_times);
- return (vms_times.proc_user_time + vms_times.proc_system_time) * 10000;
-#endif
-#endif
-#endif
+ {
+ 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) \
char *message;
rtx insn;
{
- if (!output_bytecode)
- {
- error (message);
- debug_rtx (insn);
- }
+ error (message);
+ debug_rtx (insn);
if (asm_out_file)
fflush (asm_out_file);
if (aux_info_file)
fflush (aux_info_file);
- if (rtl_dump_file)
+ if (rtl_dump_file != NULL)
fflush (rtl_dump_file);
- if (jump_opt_dump_file)
- fflush (jump_opt_dump_file);
- if (cse_dump_file)
- fflush (cse_dump_file);
- if (loop_dump_file)
- fflush (loop_dump_file);
- if (cse2_dump_file)
- fflush (cse2_dump_file);
- if (flow_dump_file)
- fflush (flow_dump_file);
- if (combine_dump_file)
- fflush (combine_dump_file);
- if (sched_dump_file)
- fflush (sched_dump_file);
- if (local_reg_dump_file)
- fflush (local_reg_dump_file);
- if (global_reg_dump_file)
- fflush (global_reg_dump_file);
- if (sched2_dump_file)
- fflush (sched2_dump_file);
- if (jump2_opt_dump_file)
- fflush (jump2_opt_dump_file);
- if (dbr_sched_dump_file)
- fflush (dbr_sched_dump_file);
- if (stack_reg_dump_file)
- fflush (stack_reg_dump_file);
fflush (stdout);
fflush (stderr);
abort ();
char *s;
va_list ap;
{
- char *n, *p;
+ char *p;
fprintf (stderr, "%s:%d: ",
DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
void
botch (s)
+ char * s;
{
abort ();
}
return value;
}
-/* Same as `realloc' but report error if no memory available. */
+/* Same as `realloc' but report error if no memory available.
+ Also handle null PTR even if the vendor realloc gets it wrong. */
char *
xrealloc (ptr, size)
char *ptr;
int size;
{
- char *result = (char *) realloc (ptr, size);
+ char *result = (ptr
+ ? (char *) realloc (ptr, size)
+ : (char *) malloc (size));
if (!result)
fatal ("virtual memory exhausted");
return result;
/* Strip off a legitimate source ending from the input string NAME of
length LEN. Rather than having to know the names used by all of
- our front ends, we strip off an ending of a period followed by one,
- two, or three characters. */
+ our front ends, we strip off an ending of a period followed by
+ up to five characters. (Java uses ".class".) */
void
strip_off_ending (name, len)
char *name;
int len;
{
- if (len > 2 && name[len - 2] == '.')
- name[len - 2] = '\0';
- else if (len > 3 && name[len - 3] == '.')
- name[len - 3] = '\0';
- else if (len > 4 && name[len - 4] == '.')
- name[len - 4] = '\0';
+ int i;
+ for (i = 2; i < 6 && len > i; i++)
+ {
+ if (name[len - i] == '.')
+ {
+ name[len - i] = '\0';
+ break;
+ }
+ }
}
/* Output a quoted string. */
FILE *asm_file;
char *string;
{
+#ifdef OUTPUT_QUOTED_STRING
+ OUTPUT_QUOTED_STRING (asm_file, string);
+#else
char c;
putc ('\"', asm_file);
putc (c, asm_file);
}
putc ('\"', asm_file);
+#endif
}
/* Output a file name in the form wanted by System V. */
}
/* Routine to open a dump file. */
+static void
+open_dump_file (suffix, function_name)
+ char *suffix;
+ char *function_name;
+{
+ char *dumpname;
+
+ TIMEVAR
+ (dump_time,
+ {
+ dumpname = (char *) xmalloc (strlen (dump_base_name) + strlen (suffix) + 1);
+
+ if (rtl_dump_file != NULL)
+ fclose (rtl_dump_file);
+
+ strcpy (dumpname, dump_base_name);
+ strcat (dumpname, suffix);
+
+ rtl_dump_file = fopen (dumpname, "a");
+
+ if (rtl_dump_file == NULL)
+ pfatal_with_name (dumpname);
+
+ free (dumpname);
+
+ if (function_name)
+ fprintf (rtl_dump_file, "\n;; Function %s\n\n", function_name);
+ });
+
+ return;
+}
-static FILE *
-open_dump_file (base_name, suffix)
- char *base_name;
+/* 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);
+
+ rtl_dump_file = NULL;
+ });
+
+ return;
+}
+
+/* Routine to dump rtl into a file. */
+static void
+dump_rtl (suffix, decl, func, insns)
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);
+}
+
+/* Routine to empty a dump file. */
+static void
+clean_dump_file (suffix)
+ char * suffix;
{
- FILE *f;
- char *dumpname = (char *) alloca (strlen (base_name) + strlen (suffix) + 1);
+ char * dumpname;
+
+ dumpname = (char *) xmalloc (strlen (dump_base_name) + strlen (suffix) + 1);
- strcpy (dumpname, base_name);
+ strcpy (dumpname, dump_base_name);
strcat (dumpname, suffix);
- f = fopen (dumpname, "w");
- if (f == 0)
- pfatal_with_name (dumpname);
- return f;
+
+ rtl_dump_file = fopen (dumpname, "w");
+
+ if (rtl_dump_file == NULL)
+ pfatal_with_name (dumpname);
+
+ free (dumpname);
+
+ fclose (rtl_dump_file);
+ rtl_dump_file = NULL;
+
+ return;
}
+
/* Compile an entire file of output from cpp, named NAME.
Write a file of assembly output and various debugging dumps. */
branch_prob_time = 0;
flow_time = 0;
combine_time = 0;
+ regmove_time = 0;
sched_time = 0;
local_alloc_time = 0;
global_alloc_time = 0;
sched2_time = 0;
+#ifdef DELAY_SLOTS
dbr_sched_time = 0;
+#endif
shorten_branch_time = 0;
stack_reg_time = 0;
final_time = 0;
symout_time = 0;
dump_time = 0;
+#if !USE_CPPLIB
/* Open input file. */
if (name == 0 || !strcmp (name, "-"))
#ifdef IO_BUFFER_SIZE
setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
#endif
+#endif /* !USE_CPPLIB */
/* Initialize data in various passes. */
init_obstacks ();
init_tree_codes ();
+#if USE_CPPLIB
+ init_parse (name);
+#else
init_lex ();
- /* Some of these really don't need to be called when generating bytecode,
- but the options would have to be parsed first to know that. -bson */
+#endif
init_rtl ();
init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE
init_expr_once ();
init_loop ();
init_reload ();
+ init_alias_once ();
if (flag_caller_saves)
init_caller_save ();
pfatal_with_name (aux_info_file_name);
}
- /* If rtl dump desired, open the output file. */
+ /* Clear the dump files file. */
if (rtl_dump)
- rtl_dump_file = open_dump_file (dump_base_name, ".rtl");
-
- /* If jump_opt dump desired, open the output file. */
+ clean_dump_file (".rtl");
if (jump_opt_dump)
- jump_opt_dump_file = open_dump_file (dump_base_name, ".jump");
-
- /* If cse dump desired, open the output file. */
+ clean_dump_file (".jump");
+ if (addressof_dump)
+ clean_dump_file (".addressof");
if (cse_dump)
- cse_dump_file = open_dump_file (dump_base_name, ".cse");
-
- /* If loop dump desired, open the output file. */
+ clean_dump_file (".cse");
if (loop_dump)
- loop_dump_file = open_dump_file (dump_base_name, ".loop");
-
- /* If cse2 dump desired, open the output file. */
+ clean_dump_file (".loop");
if (cse2_dump)
- cse2_dump_file = open_dump_file (dump_base_name, ".cse2");
-
- /* If branch_prob dump desired, open the output file. */
+ clean_dump_file (".cse2");
if (branch_prob_dump)
- branch_prob_dump_file = open_dump_file (dump_base_name, ".bp");
-
- /* If flow dump desired, open the output file. */
+ clean_dump_file (".bp");
if (flow_dump)
- flow_dump_file = open_dump_file (dump_base_name, ".flow");
-
- /* If combine dump desired, open the output file. */
+ clean_dump_file (".flow");
if (combine_dump)
- combine_dump_file = open_dump_file (dump_base_name, ".combine");
-
- /* If scheduling dump desired, open the output file. */
+ clean_dump_file (".combine");
+ if (regmove_dump)
+ clean_dump_file (".regmove");
if (sched_dump)
- sched_dump_file = open_dump_file (dump_base_name, ".sched");
-
- /* If local_reg dump desired, open the output file. */
+ clean_dump_file (".sched");
if (local_reg_dump)
- local_reg_dump_file = open_dump_file (dump_base_name, ".lreg");
-
- /* If global_reg dump desired, open the output file. */
+ clean_dump_file (".lreg");
if (global_reg_dump)
- global_reg_dump_file = open_dump_file (dump_base_name, ".greg");
-
- /* If 2nd scheduling dump desired, open the output file. */
+ clean_dump_file (".greg");
if (sched2_dump)
- sched2_dump_file = open_dump_file (dump_base_name, ".sched2");
-
- /* If jump2_opt dump desired, open the output file. */
+ clean_dump_file (".sched2");
if (jump2_opt_dump)
- jump2_opt_dump_file = open_dump_file (dump_base_name, ".jump2");
-
- /* If dbr_sched dump desired, open the output file. */
+ clean_dump_file (".jump2");
+#ifdef DELAY_SLOTS
if (dbr_sched_dump)
- dbr_sched_dump_file = open_dump_file (dump_base_name, ".dbr");
-
+ clean_dump_file (".dbr");
+#endif
#ifdef STACK_REGS
-
- /* If stack_reg dump desired, open the output file. */
if (stack_reg_dump)
- stack_reg_dump_file = open_dump_file (dump_base_name, ".stack");
-
+ clean_dump_file (".stack");
+#endif
+#ifdef MACHINE_DEPENDENT_REORG
+ if (mach_dep_reorg_dump)
+ clean_dump_file (".mach");
#endif
/* Open assembler code output file. */
input_file_stack->next = 0;
input_file_stack->name = input_filename;
+ /* Gross. Gross. lang_init is (I think) the first callback into
+ the language front end, and is thus the first opportunity to
+ have the selected language override the default value for any
+ -f option.
+
+ So the default value for flag_exceptions is 2 (uninitialized).
+ If we encounter -fno-exceptions or -fexceptions, then flag_exceptions
+ will be set to zero or one respectively.
+
+ flag_exceptions can also be set by lang_init to something other
+ than the default "uninitialized" value of 2.
+
+ After lang_init, if the value is still 2, then we default to
+ -fno-exceptions (value will be reset to zero).
+
+ When our EH mechanism is low enough overhead that we can enable
+ it by default for languages other than C++, then all this braindamage
+ will go away. */
+
/* Perform language-specific initialization.
This may set main_input_filename. */
lang_init ();
+ if (flag_exceptions == 2)
+ flag_exceptions = 0;
+
/* If the input doesn't start with a #line, use the input name
as the official input file name. */
if (main_input_filename == 0)
main_input_filename = name;
- if (!output_bytecode)
- {
- ASM_FILE_START (asm_out_file);
+ ASM_FILE_START (asm_out_file);
#ifdef ASM_COMMENT_START
- if (flag_verbose_asm)
- {
- /* Print the list of options in effect. */
- print_version (asm_out_file, ASM_COMMENT_START);
- print_switch_values (asm_out_file, 0, MAX_LINE,
+ if (flag_verbose_asm)
+ {
+ /* Print the list of options in effect. */
+ print_version (asm_out_file, ASM_COMMENT_START);
+ print_switch_values (asm_out_file, 0, MAX_LINE,
ASM_COMMENT_START, " ", "\n");
- /* Add a blank line here so it appears in assembler output but not
- screen output. */
- fprintf (asm_out_file, "\n");
- }
-#endif
+ /* Add a blank line here so it appears in assembler output but not
+ screen output. */
+ fprintf (asm_out_file, "\n");
}
+#endif
- /* Output something to inform GDB that this compilation was by GCC. Also
- serves to tell GDB file consists of bytecodes. */
- if (output_bytecode)
- fprintf (asm_out_file, "bc_gcc2_compiled.:\n");
- else
- {
+ /* Output something to inform GDB that this compilation was by GCC. */
#ifndef ASM_IDENTIFY_GCC
- fprintf (asm_out_file, "gcc2_compiled.:\n");
+ fprintf (asm_out_file, "gcc2_compiled.:\n");
#else
- ASM_IDENTIFY_GCC (asm_out_file);
+ ASM_IDENTIFY_GCC (asm_out_file);
#endif
- }
/* Output something to identify which front-end produced this file. */
#ifdef ASM_IDENTIFY_LANGUAGE
if (flag_function_sections && write_symbols != NO_DEBUG)
warning ("-ffunction-sections may affect debugging on some targets.");
- if (output_bytecode)
- {
- if (profile_flag || profile_block_flag)
- error ("profiling not supported in bytecode compilation");
- }
- else
- {
- /* ??? Note: There used to be a conditional here
- to call assemble_zeros without fail if DBX_DEBUGGING_INFO is defined.
- This was to guarantee separation between gcc_compiled. and
- the first function, for the sake of dbx on Suns.
- However, having the extra zero here confused the Emacs
- code for unexec, and might confuse other programs too.
- Therefore, I took out that change.
- In future versions we should find another way to solve
- that dbx problem. -- rms, 23 May 93. */
+ /* ??? Note: There used to be a conditional here
+ to call assemble_zeros without fail if DBX_DEBUGGING_INFO is defined.
+ This was to guarantee separation between gcc_compiled. and
+ the first function, for the sake of dbx on Suns.
+ However, having the extra zero here confused the Emacs
+ code for unexec, and might confuse other programs too.
+ Therefore, I took out that change.
+ In future versions we should find another way to solve
+ that dbx problem. -- rms, 23 May 93. */
- /* Don't let the first function fall at the same address
- as gcc_compiled., if profiling. */
- if (profile_flag || profile_block_flag)
+ /* Don't let the first function fall at the same address
+ as gcc_compiled., if profiling. */
+ if (profile_flag || profile_block_flag)
+ {
+ /* It's best if we can write a nop here since some
+ assemblers don't tolerate zeros in the text section. */
+ if (insn_template[CODE_FOR_nop] != 0)
+ output_asm_insn (insn_template[CODE_FOR_nop], NULL_PTR);
+ else
assemble_zeros (UNITS_PER_WORD);
}
if (write_symbols == DWARF_DEBUG)
TIMEVAR (symout_time, dwarfout_init (asm_out_file, main_input_filename));
#endif
+#ifdef DWARF2_UNWIND_INFO
+ if (dwarf2out_do_frame ())
+ dwarf2out_frame_init ();
+#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
TIMEVAR (symout_time, dwarf2out_init (asm_out_file, main_input_filename));
/* Initialize yet another pass. */
- if (!output_bytecode)
- init_final (main_input_filename);
+ init_final (main_input_filename);
init_branch_prob (dump_base_name);
start_time = get_run_time ();
&& DECL_INITIAL (decl) != 0
&& DECL_SAVED_INSNS (decl) != 0
&& (flag_keep_inline_functions
+ || TREE_PUBLIC (decl)
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
{
reconsider = 1;
/* Now that all possible functions have been output, we can dump
the exception table. */
- if (exception_table_p ())
- output_exception_table ();
+ output_exception_table ();
for (i = 0; i < len; i++)
{
});
#endif
+#ifdef DWARF2_UNWIND_INFO
+ if (dwarf2out_do_frame ())
+ dwarf2out_frame_finish ();
+#endif
+
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
TIMEVAR (symout_time,
/* Output some stuff at end of file if nec. */
- if (!output_bytecode)
- {
- end_final (dump_base_name);
- end_branch_prob (branch_prob_dump_file);
-
+ end_final (dump_base_name);
+
+ if (branch_prob_dump)
+ open_dump_file (".bp", NULL);
+
+ TIMEVAR (dump_time, end_branch_prob (rtl_dump_file));
+
+ if (branch_prob_dump)
+ close_dump_file (NULL, NULL_RTX);
+
#ifdef ASM_FILE_END
- ASM_FILE_END (asm_out_file);
+ ASM_FILE_END (asm_out_file);
#endif
- }
/* Language-specific end of compilation actions. */
lang_finish ();
- if (output_bytecode)
- bc_write_file (asm_out_file);
-
/* Close the dump files. */
if (flag_gen_aux_info)
unlink (aux_info_file_name);
}
- if (rtl_dump)
- fclose (rtl_dump_file);
-
- if (jump_opt_dump)
- fclose (jump_opt_dump_file);
-
- if (cse_dump)
- fclose (cse_dump_file);
-
- if (loop_dump)
- fclose (loop_dump_file);
-
- if (cse2_dump)
- fclose (cse2_dump_file);
-
- if (branch_prob_dump)
- fclose (branch_prob_dump_file);
-
- if (flow_dump)
- fclose (flow_dump_file);
-
if (combine_dump)
{
- dump_combine_total_stats (combine_dump_file);
- fclose (combine_dump_file);
+ open_dump_file (".combine", NULL);
+ TIMEVAR (dump_time, dump_combine_total_stats (rtl_dump_file));
+ close_dump_file (NULL, NULL_RTX);
}
- if (sched_dump)
- fclose (sched_dump_file);
-
- if (local_reg_dump)
- fclose (local_reg_dump_file);
-
- if (global_reg_dump)
- fclose (global_reg_dump_file);
-
- if (sched2_dump)
- fclose (sched2_dump_file);
-
- if (jump2_opt_dump)
- fclose (jump2_opt_dump_file);
-
- if (dbr_sched_dump)
- fclose (dbr_sched_dump_file);
-
-#ifdef STACK_REGS
- if (stack_reg_dump)
- fclose (stack_reg_dump_file);
-#endif
-
/* Close non-debugging input and output files. Take special care to note
whether fclose returns an error, since the pages might still be on the
buffer chain while the file is open. */
+#if USE_CPPLIB
+ finish_parse ();
+#else
fclose (finput);
+#endif
if (ferror (asm_out_file) != 0 || fclose (asm_out_file) != 0)
fatal_io_error (asm_file_name);
fprintf (stderr,"\n");
print_time ("parse", parse_time);
- if (!output_bytecode)
- {
- print_time ("integration", integration_time);
- print_time ("jump", jump_time);
- print_time ("cse", cse_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 ("sched", sched_time);
- print_time ("local-alloc", local_alloc_time);
- print_time ("global-alloc", global_alloc_time);
- print_time ("sched2", sched2_time);
- print_time ("dbranch", dbr_sched_time);
- print_time ("shorten-branch", shorten_branch_time);
- print_time ("stack-reg", stack_reg_time);
- print_time ("final", final_time);
- print_time ("varconst", varconst_time);
- print_time ("symout", symout_time);
- print_time ("dump", dump_time);
- }
+ print_time ("integration", integration_time);
+ print_time ("jump", jump_time);
+ print_time ("cse", cse_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);
+ print_time ("sched", sched_time);
+ print_time ("local-alloc", local_alloc_time);
+ print_time ("global-alloc", global_alloc_time);
+ print_time ("sched2", sched2_time);
+#ifdef DELAY_SLOTS
+ print_time ("dbranch", dbr_sched_time);
+#endif
+ print_time ("shorten-branch", shorten_branch_time);
+ print_time ("stack-reg", stack_reg_time);
+ print_time ("final", final_time);
+ print_time ("varconst", varconst_time);
+ print_time ("symout", symout_time);
+ print_time ("dump", dump_time);
}
}
\f
&& (DECL_INITIAL (decl) == 0
|| DECL_INITIAL (decl) == error_mark_node)))
assemble_variable (decl, top_level, at_end, 0);
- if (!output_bytecode
- && decl == last_assemble_variable_decl)
+ if (decl == last_assemble_variable_decl)
{
ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
top_level, at_end);
tree saved_arguments = 0;
int failure = 0;
- if (output_bytecode)
- return;
-
/* If we are reconsidering an inline function
at the end of compilation, skip the stuff for making it inline. */
if (DECL_SAVED_INSNS (decl) == 0)
{
- int inlineable = 0;
+ int inlinable = 0;
char *lose;
/* If requested, consider whether to make this function inline. */
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. */
- inlineable = DECL_INLINE (decl) = 1;
+ inlinable = DECL_INLINE (decl) = 1;
});
insns = get_insns ();
/* Dump the rtl code if we are dumping rtl. */
if (rtl_dump)
- TIMEVAR (dump_time,
- {
- fprintf (rtl_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- if (DECL_SAVED_INSNS (decl))
- fprintf (rtl_dump_file, ";; (integrable)\n\n");
- print_rtl (rtl_dump_file, insns);
- fflush (rtl_dump_file);
- });
+ {
+ open_dump_file (".rtl", decl_printable_name (decl, 2));
+
+ if (DECL_SAVED_INSNS (decl))
+ fprintf (rtl_dump_file, ";; (integrable)\n\n");
+
+ close_dump_file (print_rtl, insns);
+ }
+
+ /* If we can, defer compiling inlines until EOF.
+ save_for_inline_copying can be extremely expensive. */
+ if (inlinable && ! decl_function_context (decl))
+ DECL_DEFER_OUTPUT (decl) = 1;
/* If function is inline, and we don't yet know whether to
compile it by itself, defer decision till end of compilation.
functions containing nested functions since the nested function
data is in our non-saved obstack. */
+ /* If this is a nested inline, remove ADDRESSOF now so we can
+ finish compiling ourselves. Otherwise, wait until EOF.
+ We have to do this because the purge_addressof transformation
+ changes the DECL_RTL for many variables, which confuses integrate. */
+ if (inlinable)
+ {
+ if (decl_function_context (decl))
+ purge_addressof (insns);
+ else
+ DECL_DEFER_OUTPUT (decl) = 1;
+ }
+
if (! current_function_contains_functions
&& (DECL_DEFER_OUTPUT (decl)
|| (DECL_INLINE (decl)
{
DECL_DEFER_OUTPUT (decl) = 1;
- /* If -Wreturn-type, we have to do a bit of compilation. */
- if (! warn_return_type)
+ /* 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
+ memory use. Instead, we just want to call
+ jump_optimize() to figure out whether or not we can fall
+ off the end of the function; we do the minimum amount of
+ work necessary to make that safe. And, we set optimize
+ to zero to keep jump_optimize from working too hard. */
+ if (warn_return_type)
{
+ int saved_optimize = optimize;
+ optimize = 0;
+ find_exception_handler_labels ();
+ jump_optimize (get_insns(), 0, 0, 0);
+ 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);
- }
+ /* 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));
- RTX_INTEGRATED_P (DECL_SAVED_INSNS (decl)) = inlineable;
- goto exit_rest_of_compilation;
+ /* 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));
+ RTX_INTEGRATED_P (DECL_SAVED_INSNS (decl)) = inlinable;
+ goto exit_rest_of_compilation;
}
/* If we have to compile the function now, save its rtl and subdecls
so that its compilation will not affect what others get. */
- if (inlineable || DECL_DEFER_OUTPUT (decl))
+ if (inlinable || DECL_DEFER_OUTPUT (decl))
{
#ifdef DWARF_DEBUGGING_INFO
/* Generate the DWARF info for the "abstract" instance of
saved_block_tree = DECL_INITIAL (decl);
saved_arguments = DECL_ARGUMENTS (decl);
TIMEVAR (integration_time, save_for_inline_copying (decl));
- RTX_INTEGRATED_P (DECL_SAVED_INSNS (decl)) = inlineable;
+ RTX_INTEGRATED_P (DECL_SAVED_INSNS (decl)) = inlinable;
}
/* If specified extern inline but we aren't inlining it, we are
goto exit_rest_of_compilation;
}
- /* Add an unwinder for exception handling, if needed.
- This must be done before we finalize PIC code. */
- emit_unwinder ();
+ /* Emit code to get eh context, if needed. */
+ emit_eh_context ();
#ifdef FINALIZE_PIC
/* If we are doing position-independent code generation, now
unshare_all_rtl (insns);
+#ifdef SETJMP_VIA_SAVE_AREA
+ /* This must be performed before virutal register instantiation. */
+ if (current_function_calls_alloca)
+ optimize_save_area_alloca (insns);
+#endif
+
/* Instantiate all virtual registers. */
instantiate_virtual_regs (current_function_decl, get_insns ());
/* Dump rtl code after jump, if we are doing that. */
- if (jump_opt_dump)
- TIMEVAR (dump_time,
- {
- fprintf (jump_opt_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- print_rtl (jump_opt_dump_file, insns);
- fflush (jump_opt_dump_file);
- });
+ if (jump_opt_dump)
+ dump_rtl (".jump", decl, print_rtl, insns);
/* Perform common subexpression elimination.
Nonzero value from `cse_main' means that jumps were simplified
and some code may now be unreachable, so do
jump optimization again. */
- if (cse_dump)
- TIMEVAR (dump_time,
- {
- fprintf (cse_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- });
-
if (optimize > 0)
{
+ if (cse_dump)
+ open_dump_file (".cse", decl_printable_name (decl, 2));
+
TIMEVAR (cse_time, reg_scan (insns, max_reg_num (), 1));
if (flag_thread_jumps)
TIMEVAR (jump_time, thread_jumps (insns, max_reg_num (), 1));
TIMEVAR (cse_time, tem = cse_main (insns, max_reg_num (),
- 0, cse_dump_file));
+ 0, rtl_dump_file));
TIMEVAR (cse_time, delete_dead_from_cse (insns, max_reg_num ()));
if (tem || optimize > 1)
TIMEVAR (jump_time, jump_optimize (insns, 0, 0, 0));
- }
-
- /* Dump rtl code after cse, if we are doing that. */
- if (cse_dump)
- TIMEVAR (dump_time,
- {
- print_rtl (cse_dump_file, insns);
- fflush (cse_dump_file);
- });
+ /* Dump rtl code after cse, if we are doing that. */
+
+ if (cse_dump)
+ close_dump_file (print_rtl, insns);
+ }
- if (loop_dump)
- TIMEVAR (dump_time,
- {
- fprintf (loop_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- });
+ purge_addressof (insns);
+ reg_scan (insns, max_reg_num (), 1);
+ if (addressof_dump)
+ dump_rtl (".addressof", decl, print_rtl, insns);
+
/* Move constant computations out of loops. */
if (optimize > 0)
{
- TIMEVAR (loop_time,
- {
- loop_optimize (insns, loop_dump_file);
- });
- }
-
- /* Dump rtl code after loop opt, if we are doing that. */
-
- if (loop_dump)
- TIMEVAR (dump_time,
- {
- print_rtl (loop_dump_file, insns);
- fflush (loop_dump_file);
- });
-
- if (cse2_dump)
- TIMEVAR (dump_time,
+ if (loop_dump)
+ open_dump_file (".loop", decl_printable_name (decl, 2));
+
+ TIMEVAR
+ (loop_time,
+ {
+ if (flag_rerun_loop_opt)
{
- fprintf (cse2_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- });
-
- if (optimize > 0 && flag_rerun_cse_after_loop)
- {
- /* Running another jump optimization pass before the second
- cse pass sometimes simplifies the RTL enough to allow
- 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, 0, 0, 1));
-
- TIMEVAR (cse2_time, reg_scan (insns, max_reg_num (), 0));
- TIMEVAR (cse2_time, tem = cse_main (insns, max_reg_num (),
- 1, cse2_dump_file));
- if (tem)
- TIMEVAR (jump_time, jump_optimize (insns, 0, 0, 0));
+ /* We only want to perform unrolling once. */
+
+ loop_optimize (insns, rtl_dump_file, 0);
+
+ /* The regscan pass may not be necessary, but let's
+ be safe until we can prove otherwise. */
+ reg_scan (insns, max_reg_num (), 1);
+ }
+ loop_optimize (insns, rtl_dump_file, flag_unroll_loops);
+ });
+
+ /* Dump rtl code after loop opt, if we are doing that. */
+
+ if (loop_dump)
+ close_dump_file (print_rtl, insns);
}
- if (optimize > 0 && flag_thread_jumps)
+ if (optimize > 0)
{
- /* 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));
- }
- /* Dump rtl code after cse, if we are doing that. */
-
- if (cse2_dump)
- TIMEVAR (dump_time,
- {
- print_rtl (cse2_dump_file, insns);
- fflush (cse2_dump_file);
- });
-
- if (branch_prob_dump)
- TIMEVAR (dump_time,
- {
- fprintf (branch_prob_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- });
+ if (cse2_dump)
+ open_dump_file (".cse2", decl_printable_name (decl, 2));
+
+ if (flag_rerun_cse_after_loop)
+ {
+ /* Running another jump optimization pass before the second
+ cse pass sometimes simplifies the RTL enough to allow
+ 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, 0, 0, 1));
+
+ TIMEVAR (cse2_time, reg_scan (insns, max_reg_num (), 0));
+ TIMEVAR (cse2_time, tem = cse_main (insns, max_reg_num (),
+ 1, rtl_dump_file));
+ if (tem)
+ TIMEVAR (jump_time, jump_optimize (insns, 0, 0, 0));
+ }
+ 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));
+ }
+
+ /* Dump rtl code after cse, if we are doing that. */
+
+ if (cse2_dump)
+ close_dump_file (print_rtl, insns);
+ }
+
if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
- TIMEVAR (branch_prob_time,
- {
- branch_prob (insns, branch_prob_dump_file);
- });
-
- if (branch_prob_dump)
- TIMEVAR (dump_time,
- {
- print_rtl (branch_prob_dump_file, insns);
- fflush (branch_prob_dump_file);
- });
+ {
+ if (branch_prob_dump)
+ open_dump_file (".bp", decl_printable_name (decl, 2));
+
+ TIMEVAR
+ (branch_prob_time,
+ {
+ branch_prob (insns, rtl_dump_file);
+ });
+
+ if (branch_prob_dump)
+ close_dump_file (print_rtl, insns);
+ }
+
/* We are no longer anticipating cse in this function, at least. */
cse_not_expected = 1;
because doing the flow analysis makes some of the dump. */
if (flow_dump)
- TIMEVAR (dump_time,
- {
- fprintf (flow_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- });
-
+ open_dump_file (".flow", decl_printable_name (decl, 2));
+
if (obey_regdecls)
{
TIMEVAR (flow_time,
{
regclass (insns, max_reg_num ());
stupid_life_analysis (insns, max_reg_num (),
- flow_dump_file);
+ rtl_dump_file);
});
}
else
/* Do control and data flow analysis,
and write some of the results to dump file. */
- TIMEVAR (flow_time, flow_analysis (insns, max_reg_num (),
- flow_dump_file));
+ TIMEVAR
+ (flow_time,
+ {
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
+ life_analysis (insns, max_reg_num (), rtl_dump_file);
+ });
+
if (warn_uninitialized)
{
uninitialized_vars_warning (DECL_INITIAL (decl));
/* Dump rtl after flow analysis. */
if (flow_dump)
- TIMEVAR (dump_time,
- {
- print_rtl (flow_dump_file, insns);
- fflush (flow_dump_file);
- });
-
+ close_dump_file (print_rtl_with_bb, insns);
+
/* If -opt, try combining insns through substitution. */
if (optimize > 0)
- TIMEVAR (combine_time, combine_instructions (insns, max_reg_num ()));
-
- /* Dump rtl code after insn combination. */
+ {
+ TIMEVAR (combine_time, combine_instructions (insns, max_reg_num ()));
+
+ /* Dump rtl code after insn combination. */
+
+ if (combine_dump)
+ dump_rtl (".combine", decl, print_rtl_with_bb, insns);
+ }
- if (combine_dump)
- TIMEVAR (dump_time,
- {
- fprintf (combine_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- dump_combine_stats (combine_dump_file);
- print_rtl (combine_dump_file, insns);
- fflush (combine_dump_file);
- });
+ /* 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 (".regmove", decl_printable_name (decl, 2));
+
+ TIMEVAR (regmove_time, regmove_optimize (insns, max_reg_num (),
+ rtl_dump_file));
+
+ if (regmove_dump)
+ close_dump_file (print_rtl_with_bb, insns);
+ }
/* Print function header into sched dump now
because doing the sched analysis makes some of the dump. */
- if (sched_dump)
- TIMEVAR (dump_time,
- {
- fprintf (sched_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- });
-
if (optimize > 0 && flag_schedule_insns)
{
+ if (sched_dump)
+ open_dump_file (".sched", decl_printable_name (decl, 2));
+
/* Do control and data sched analysis,
and write some of the results to dump file. */
- TIMEVAR (sched_time, schedule_insns (sched_dump_file));
+ TIMEVAR (sched_time, schedule_insns (rtl_dump_file));
+
+ /* Dump rtl after instruction scheduling. */
+
+ if (sched_dump)
+ close_dump_file (print_rtl_with_bb, insns);
}
- /* Dump rtl after instruction scheduling. */
-
- if (sched_dump)
- TIMEVAR (dump_time,
- {
- print_rtl (sched_dump_file, insns);
- fflush (sched_dump_file);
- });
-
/* Unless we did stupid register allocation,
allocate pseudo-regs that are used only within 1 basic block. */
/* Dump rtl code after allocating regs within basic blocks. */
if (local_reg_dump)
- TIMEVAR (dump_time,
- {
- fprintf (local_reg_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- dump_flow_info (local_reg_dump_file);
- dump_local_alloc (local_reg_dump_file);
- print_rtl (local_reg_dump_file, insns);
- fflush (local_reg_dump_file);
- });
+ {
+ open_dump_file (".lreg", decl_printable_name (decl, 2));
+
+ TIMEVAR (dump_time, dump_flow_info (rtl_dump_file));
+ TIMEVAR (dump_time, dump_local_alloc (rtl_dump_file));
+
+ close_dump_file (print_rtl_with_bb, insns);
+ }
if (global_reg_dump)
- TIMEVAR (dump_time,
- fprintf (global_reg_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl))));
+ open_dump_file (".greg", decl_printable_name (decl, 2));
/* Save the last label number used so far, so reorg can tell
when it's safe to kill spill regs. */
TIMEVAR (global_alloc_time,
{
if (!obey_regdecls)
- failure = global_alloc (global_reg_dump_file);
+ failure = global_alloc (rtl_dump_file);
else
- failure = reload (insns, 0, global_reg_dump_file);
+ failure = reload (insns, 0, rtl_dump_file);
});
if (global_reg_dump)
- TIMEVAR (dump_time,
- {
- dump_global_regs (global_reg_dump_file);
- print_rtl (global_reg_dump_file, insns);
- fflush (global_reg_dump_file);
- });
+ {
+ TIMEVAR (dump_time, dump_global_regs (rtl_dump_file));
+ close_dump_file (print_rtl_with_bb, insns);
+ }
if (failure)
goto exit_rest_of_compilation;
if (optimize > 0 && flag_schedule_insns_after_reload)
{
if (sched2_dump)
- TIMEVAR (dump_time,
- {
- fprintf (sched2_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- });
+ open_dump_file (".sched2", decl_printable_name (decl, 2));
/* Do control and data sched analysis again,
and write some more of the results to dump file. */
- TIMEVAR (sched2_time, schedule_insns (sched2_dump_file));
+ TIMEVAR (sched2_time, schedule_insns (rtl_dump_file));
/* Dump rtl after post-reorder instruction scheduling. */
if (sched2_dump)
- TIMEVAR (dump_time,
- {
- print_rtl (sched2_dump_file, insns);
- fflush (sched2_dump_file);
- });
+ close_dump_file (print_rtl_with_bb, insns);
}
#ifdef LEAF_REGISTERS
if (optimize > 0)
{
TIMEVAR (jump_time, jump_optimize (insns, 1, 1, 0));
- }
-
- /* Dump rtl code after jump, if we are doing that. */
+
+ /* Dump rtl code after jump, if we are doing that. */
- if (jump2_opt_dump)
- TIMEVAR (dump_time,
- {
- fprintf (jump2_opt_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- print_rtl (jump2_opt_dump_file, insns);
- fflush (jump2_opt_dump_file);
- });
+ if (jump2_opt_dump)
+ dump_rtl (".jump2", decl, print_rtl_with_bb, insns);
+ }
/* If a machine dependent reorganization is needed, call it. */
#ifdef MACHINE_DEPENDENT_REORG
MACHINE_DEPENDENT_REORG (insns);
+
+ if (mach_dep_reorg_dump)
+ dump_rtl (".mach", decl, print_rtl_with_bb, insns);
#endif
/* If a scheduling pass for delayed branches is to be done,
#ifdef DELAY_SLOTS
if (optimize > 0 && flag_delayed_branch)
{
- TIMEVAR (dbr_sched_time, dbr_schedule (insns, dbr_sched_dump_file));
+ TIMEVAR (dbr_sched_time, dbr_schedule (insns, rtl_dump_file));
+
if (dbr_sched_dump)
- {
- TIMEVAR (dump_time,
- {
- fprintf (dbr_sched_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- print_rtl (dbr_sched_dump_file, insns);
- fflush (dbr_sched_dump_file);
- });
- }
+ dump_rtl (".dbr", decl, print_rtl_with_bb, insns);
}
#endif
});
#ifdef STACK_REGS
- TIMEVAR (stack_reg_time, reg_to_stack (insns, stack_reg_dump_file));
+ TIMEVAR (stack_reg_time, reg_to_stack (insns, rtl_dump_file));
+
if (stack_reg_dump)
- {
- TIMEVAR (dump_time,
- {
- fprintf (stack_reg_dump_file, "\n;; Function %s\n\n",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- print_rtl (stack_reg_dump_file, insns);
- fflush (stack_reg_dump_file);
- });
- }
+ dump_rtl (".stack", decl, print_rtl_with_bb, insns);
#endif
/* Now turn the rtl into assembler code. */
final (insns, asm_out_file, optimize, 0);
final_end_function (insns, asm_out_file, optimize);
assemble_end_function (decl, fnname);
- fflush (asm_out_file);
+ if (! quiet_flag)
+ fflush (asm_out_file);
/* Release all memory held by regsets now */
regset_release_memory ();
init_temp_slots ();
+ /* Make sure volatile mem refs aren't considered valid operands for
+ arithmetic insns. We must call this here if this is a nested inline
+ function, since the above code leaves us in the init_recog state
+ (from final.c), and the function context push/pop code does not
+ save/restore volatile_ok.
+
+ ??? Maybe it isn't necessary for expand_start_function to call this
+ anymore if we do it here? */
+
+ init_recog_no_volatile ();
+
/* The parsing time is all the time spent in yyparse
*except* what is spent in this function. */
--p;
progname = p;
-#ifdef RLIMIT_STACK
+#if defined (RLIMIT_STACK) && defined (HAVE_GETRLIMIT) && defined (HAVE_SETRLIMIT)
/* Get rid of any avoidable limit on stack size. */
{
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max;
setrlimit (RLIMIT_STACK, &rlim);
}
-#endif /* RLIMIT_STACK */
+#endif
signal (SIGFPE, float_signal);
}
else if (argv[i][0] == '-' && argv[i][1] == 'O')
{
- /* Handle -O2, -O3, -O69, ... */
+ /* Handle -Os, -O2, -O3, -O69, ... */
char *p = &argv[i][2];
int c;
-
- while (c = *p++)
- if (! (c >= '0' && c <= '9'))
- break;
- if (c == 0)
- optimize = atoi (&argv[i][2]);
+
+ if ((p[0] == 's') && (p[1] == 0))
+ optimize_size = 1;
+ else
+ {
+ while ((c = *p++))
+ if (! (c >= '0' && c <= '9'))
+ break;
+ if (c == 0)
+ optimize = atoi (&argv[i][2]);
+ }
}
}
+ /* Optimizing for size forces optimize to be no less than 2. */
+ if (optimize_size && (optimize < 2))
+ optimize = 2;
+
obey_regdecls = (optimize == 0);
if (optimize >= 1)
flag_expensive_optimizations = 1;
flag_strength_reduce = 1;
flag_rerun_cse_after_loop = 1;
+ flag_rerun_loop_opt = 1;
flag_caller_saves = 1;
flag_force_mem = 1;
#ifdef INSN_SCHEDULING
flag_schedule_insns = 1;
flag_schedule_insns_after_reload = 1;
#endif
+ flag_regmove = 1;
}
if (optimize >= 3)
#ifdef OPTIMIZATION_OPTIONS
/* Allow default optimizations to be specified on a per-machine basis. */
- OPTIMIZATION_OPTIONS (optimize);
+ OPTIMIZATION_OPTIONS (optimize, optimize_size);
#endif
/* Initialize register usage now so switches may override. */
for (i = 1; i < argc; i++)
{
- int j;
+ size_t j;
/* If this is a language-specific option,
decode it in a language-specific way. */
for (j = 0; lang_options[j] != 0; j++)
case 'a':
branch_prob_dump = 1;
combine_dump = 1;
+#ifdef DELAY_SLOTS
dbr_sched_dump = 1;
+#endif
flow_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;
sched_dump = 1;
sched2_dump = 1;
+#ifdef STACK_REGS
stack_reg_dump = 1;
+#endif
+#ifdef MACHINE_DEPENDENT_REORG
+ mach_dep_reorg_dump = 1;
+#endif
break;
case 'b':
branch_prob_dump = 1;
break;
+#ifdef STACK_REGS
case 'k':
stack_reg_dump = 1;
break;
+#endif
case 'c':
combine_dump = 1;
break;
+#ifdef DELAY_SLOTS
case 'd':
dbr_sched_dump = 1;
break;
+#endif
case 'f':
flow_dump = 1;
break;
case 'j':
jump_opt_dump = 1;
break;
+ case 'D':
+ addressof_dump = 1;
+ break;
case 'J':
jump2_opt_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 't':
cse2_dump = 1;
break;
+ case 'N':
+ regmove_dump = 1;
+ break;
case 'S':
sched_dump = 1;
break;
case 'A':
flag_debug_asm = 1;
break;
+ default:
+ warning ("unrecognised gcc debugging option: %c", p[-1]);
+ break;
}
}
else if (str[0] == 'f')
if (found)
;
+#ifdef HAIFA
+#ifdef INSN_SCHEDULING
+ else if (!strncmp (p, "sched-verbose-",14))
+ fix_sched_param("verbose",&p[14]);
+ else if (!strncmp (p, "sched-max-",10))
+ fix_sched_param("max",&p[10]);
+ else if (!strncmp (p, "sched-inter-max-b-",18))
+ fix_sched_param("interblock-max-blocks",&p[18]);
+ else if (!strncmp (p, "sched-inter-max-i-",18))
+ fix_sched_param("interblock-max-insns",&p[18]);
+#endif
+#endif /* HAIFA */
else if (!strncmp (p, "fixed-", 6))
fix_register (&p[6], 1, 1);
else if (!strncmp (p, "call-used-", 10))
else if (str[0] == 'O')
{
register char *p = str+1;
- while (*p && *p >= '0' && *p <= '9')
+ if (*p == 's')
p++;
+ else
+ while (*p && *p >= '0' && *p <= '9')
+ p++;
if (*p == '\0')
;
else
p = str + strlen (da->arg);
if (*p && (*p < '0' || *p > '9'))
continue;
+ len = p - str;
q = p;
while (*q && (*q >= '0' && *q <= '9'))
q++;
if (*p)
- level = atoi (p);
+ {
+ level = atoi (p);
+ if (len > 1 && !strncmp (str, "gdwarf", len))
+ {
+ error ("use -gdwarf -g%d for DWARF v1, level %d",
+ level, level);
+ if (level == 2)
+ error ("use -gdwarf-2 for DWARF v2");
+ }
+ }
else
level = 2; /* default debugging info level */
if (*q || level > 3)
type = PREFERRED_DEBUGGING_TYPE;
if (len > 1 && strncmp (str, "ggdb", len) == 0)
{
-#ifdef DWARF2_DEBUGGING_INFO
+#if defined (DWARF2_DEBUGGING_INFO) && !defined (LINKER_DOES_NOT_WORK_WITH_DWARF2)
type = DWARF2_DEBUG;
-#elif defined DBX_DEBUGGING_INFO
+#else
+#ifdef DBX_DEBUGGING_INFO
type = DBX_DEBUG;
+#endif
#endif
}
}
filename = argv[i];
}
- /* Initialize for bytecode output. A good idea to do this as soon as
- possible after the "-f" options have been parsed. */
- if (output_bytecode)
- {
-#ifndef TARGET_SUPPORTS_BYTECODE
- /* Just die with a fatal error if not supported */
- fatal ("-fbytecode not supported for this target");
-#else
- bc_initialize ();
-#endif
- }
+ /* Checker uses the frame pointer. */
+ if (flag_check_memory_usage)
+ flag_omit_frame_pointer = 0;
if (optimize == 0)
{
OVERRIDE_OPTIONS;
#endif
+ if (exceptions_via_longjmp == 2)
+ {
+#ifdef DWARF2_UNWIND_INFO
+ exceptions_via_longjmp = ! DWARF2_UNWIND_INFO;
+#else
+ exceptions_via_longjmp = 1;
+#endif
+ }
+
if (profile_block_flag == 3)
{
warning ("`-ax' and `-a' are conflicting options. `-a' ignored.");
lim - (char *) &environ);
fflush (stderr);
+#ifndef __MSDOS__
#ifdef USG
system ("ps -l 1>&2");
#else /* not USG */
system ("ps v");
#endif /* not USG */
+#endif
}
#endif /* ! OS2 && ! VMS && (! _WIN32 || CYGWIN32) */
set_target_switch (name)
char *name;
{
- register int j;
+ register size_t j;
int valid = 0;
for (j = 0; j < sizeof target_switches / sizeof target_switches[0]; j++)
int pos, max;
char *indent, *sep, *term;
{
- int j, flags;
+ size_t j;
char **p;
/* Print the options as passed. */
/* Print target specific options. */
- flags = target_flags;
for (j = 0; j < sizeof target_switches / sizeof target_switches[0]; j++)
if (target_switches[j].name[0] != '\0'
&& target_switches[j].value > 0
{
pos = print_single_switch (file, pos, max, indent, sep, term,
"-m", target_switches[j].name);
- flags &= ~ target_switches[j].value;
}
#ifdef TARGET_OPTIONS