/* Top level of GNU C compiler
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000 Free Software Foundation, Inc.
+ 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
#include "tm_p.h"
#include "flags.h"
#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 "except.h"
#include "function.h"
#include "timevar.h"
#include "diagnostic.h"
#include "ssa.h"
-
-#ifndef ACCUMULATE_OUTGOING_ARGS
-#define ACCUMULATE_OUTGOING_ARGS 0
-#endif
+#include "params.h"
+#include "reload.h"
+#include "dwarf2asm.h"
#ifdef DWARF_DEBUGGING_INFO
#include "dwarfout.h"
static void float_signal PARAMS ((int)) ATTRIBUTE_NORETURN;
static void crash_signal PARAMS ((int)) ATTRIBUTE_NORETURN;
-#ifdef ASM_IDENTIFY_LANGUAGE
-/* This might or might not be used in ASM_IDENTIFY_LANGUAGE. */
-static void output_lang_identify PARAMS ((FILE *)) ATTRIBUTE_UNUSED;
-#endif
static void compile_file PARAMS ((const char *));
static void display_help PARAMS ((void));
static void display_target_options PARAMS ((void));
const char *progname;
-/* Copy of arguments to main. */
+/* Copy of arguments to toplev_main. */
int save_argc;
char **save_argv;
\f
{
DFI_rtl,
DFI_sibling,
+ DFI_eh,
DFI_jump,
DFI_cse,
DFI_addressof,
Remaining -d letters:
- " h o q u "
+ " o q u "
" H K OPQ TUVW YZ"
*/
{
{ "rtl", 'r', 0, 0, 0 },
{ "sibling", 'i', 0, 0, 0 },
+ { "eh", 'h', 0, 0, 0 },
{ "jump", 'j', 0, 0, 0 },
{ "cse", 's', 0, 0, 0 },
{ "addressof", 'F', 0, 0, 0 },
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;
int warningcount = 0;
int sorrycount = 0;
+/* Nonzero if we should exit after parsing options. */
+static int exit_after_options = 0;
+
/* The FUNCTION_DECL for the function currently being compiled,
or 0 if between functions. */
tree current_function_decl;
int flag_no_peephole = 0;
-/* Nonzero allows GCC to violate some IEEE or ANSI rules regarding math
- operations in the interest of optimization. For example it allows
- GCC to assume arguments to sqrt are nonnegative numbers, allowing
- faster code for sqrt to be generated. */
-
-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. */
+ operations, like built-in SQRT. */
int flag_errno_math = 1;
+/* Nonzero means that unsafe floating-point math optimizations are allowed
+ for the sake of speed. IEEE compliance is not guaranteed, and operations
+ are allowed to assume that their arguments and results are "normal"
+ (e.g., nonnegative for SQRT). */
+
+int flag_unsafe_math_optimizations = 0;
+
+/* Zero means that floating-point math operations cannot generate a
+ (user-visible) trap. This is the case, for example, in nonstop
+ IEEE 754 arithmetic. */
+
+int flag_trapping_math = 1;
+
/* 0 means straightforward implementation of complex divide acceptable.
1 means wide ranges of inputs must work for complex divide.
2 means C99-like requirements for complex divide (not yet implemented). */
static int flag_delete_null_pointer_checks;
+/* Nonzero means to do the enhanced load motion during gcse, which trys
+ to hoist loads by not killing them when a store to the same location
+ is seen. */
+
+int flag_gcse_lm = 1;
+
+/* Nonzero means to perform store motion after gcse, which will try to
+ move stores closer to the exit block. Its not very effective without
+ flag_gcse_lm. */
+
+int flag_gcse_sm = 1;
+
/* Nonzero means to rerun cse after loop optimization. This increases
compilation time about 20% and picks up a few more common expressions. */
int flag_exceptions;
-/* Nonzero means use the new model for exception handling. Replaces
- -DNEW_EH_MODEL as a compile option. */
-
-int flag_new_exceptions = 1;
-
/* Nonzero means generate frame unwind info table when supported. */
int flag_unwind_tables = 0;
/* This will perform a peephole pass before sched2. */
int flag_peephole2 = 0;
+/* This will try to guess branch probabilities. */
+int flag_guess_branch_prob = 0;
+
/* -fbounded-pointers causes gcc to compile pointers as composite
objects occupying three words: the pointer value, the base address
of the referent object, and the address immediately beyond the end
/* The user symbol prefix after having resolved same. */
const char *user_label_prefix;
+static const param_info lang_independent_params[] = {
+#define DEFPARAM(ENUM, OPTION, HELP, DEFAULT) \
+ { OPTION, DEFAULT, HELP },
+#include "params.def"
+#undef DEFPARAM
+ { NULL, 0, NULL }
+};
+
/* A default for same. */
#ifndef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX ""
lang_independent_options f_options[] =
{
- {"eliminate-dwarf2-dups", &flag_eliminate_dwarf2_dups, 1,
+ {"eliminate-dwarf2-dups", &flag_eliminate_dwarf2_dups, 1,
"Perform DWARF2 duplicate elimination"},
{"float-store", &flag_float_store, 1,
"Do not store floats in registers" },
"Attempt to fill delay slots of branch instructions" },
{"gcse", &flag_gcse, 1,
"Perform the global common subexpression elimination" },
+ {"gcse-lm", &flag_gcse_lm, 1,
+ "Perform enhanced load motion during global subexpression elimination" },
+ {"gcse-sm", &flag_gcse_sm, 1,
+ "Perform store motion after global subexpression elimination" },
{"rerun-cse-after-loop", &flag_rerun_cse_after_loop, 1,
"Run CSE pass after loop optimisations"},
{"rerun-loop-opt", &flag_rerun_loop_opt, 1,
{"pretend-float", &flag_pretend_float, 1,
"Pretend that host and target use the same FP format"},
{"schedule-insns", &flag_schedule_insns, 1,
- "Reschedule instructions to avoid pipeline stalls"},
+ "Reschedule instructions before register allocation"},
{"schedule-insns2", &flag_schedule_insns_after_reload, 1,
- "Run two passes of the instruction scheduler"},
+ "Reschedule instructions after register allocation"},
{"sched-interblock",&flag_schedule_interblock, 1,
"Enable scheduling across basic blocks" },
{"sched-spec",&flag_schedule_speculative, 1,
{"PIC", &flag_pic, 2, ""},
{"exceptions", &flag_exceptions, 1,
"Enable exception handling" },
- {"new-exceptions", &flag_new_exceptions, 1,
- "Use the new model for exception handling" },
{"unwind-tables", &flag_unwind_tables, 1,
"Just generate unwind tables for exception handling" },
- {"sjlj-exceptions", &exceptions_via_longjmp, 1,
- "Use setjmp/longjmp to handle exceptions" },
- {"asynchronous-exceptions", &asynchronous_exceptions, 1,
- "Support asynchronous exceptions" },
+ {"non-call-exceptions", &flag_non_call_exceptions, 1,
+ "Support synchronous non-call exceptions" },
{"profile-arcs", &profile_arc_flag, 1,
"Insert arc based program profiling code" },
{"test-coverage", &flag_test_coverage, 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,
"Do not put unitialised globals in the common section" },
{"inhibit-size-directive", &flag_inhibit_size_directive, 1,
"Process #ident directives"},
{ "peephole2", &flag_peephole2, 1,
"Enables an rtl peephole pass run before sched2" },
+ { "guess-branch-probability", &flag_guess_branch_prob, 1,
+ "Enables guessing of branch probabilities" },
{"math-errno", &flag_errno_math, 1,
"Set errno after built-in math functions"},
+ {"trapping-math", &flag_trapping_math, 1,
+ "Floating-point operations can trap"},
+ {"unsafe-math-optimizations", &flag_unsafe_math_optimizations, 1,
+ "Allow math optimizations that may violate IEEE or ANSI standards"},
{"bounded-pointers", &flag_bounded_pointers, 1,
"Compile pointers as triples: value, base & end" },
{"bounds-check", &flag_bounds_check, 1,
{ "-Wbad-function-cast",
"Warn about casting functions to incompatible types" },
{ "-Wno-bad-function-cast", "" },
- { "-Wmissing-noreturn",
- "Warn about functions which might be candidates for attribute noreturn" },
{ "-Wno-missing-noreturn", "" },
{ "-Wmissing-format-attribute",
"Warn about functions which might be candidates for format attributes" },
{ "-Wno-comments", "" },
{ "-Wconversion", "Warn about possibly confusing type conversions" },
{ "-Wno-conversion", "" },
- { "-Wformat", "Warn about printf/scanf/strftime format anomalies" },
+ { "-Wformat", "Warn about printf/scanf/strftime/strfmon format anomalies" },
{ "-Wno-format", "" },
{ "-Wformat-y2k", "" },
{ "-Wno-format-y2k",
"Don't warn about too many arguments to format functions" },
{ "-Wformat-nonliteral", "Warn about non-string-literal format strings" },
{ "-Wno-format-nonliteral", "" },
+ { "-Wformat-security",
+ "Warn about possible security problems with format functions" },
+ { "-Wno-format-security", "" },
{ "-Wimplicit-function-declaration",
"Warn about implicit function declarations" },
{ "-Wno-implicit-function-declaration", "" },
characters. The value N is in `id_clash_len'. */
int warn_id_clash;
-int id_clash_len;
+unsigned 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
{"padded", &warn_padded, 1,
"Warn when padding is required to align struct members"},
{"disabled-optimization", &warn_disabled_optimization, 1,
- "Warn when an optimization pass is disabled"}
+ "Warn when an optimization pass is disabled"},
+ {"missing-noreturn", &warn_missing_noreturn, 1,
+ "Warn about functions which might be candidates for attribute noreturn"}
};
+
+/* The following routines are useful in setting all the flags that
+ -ffast-math and -fno-fast-math imply. */
+
+void
+set_fast_math_flags ()
+{
+ flag_trapping_math = 0;
+ flag_unsafe_math_optimizations = 1;
+ flag_errno_math = 0;
+}
+
+void
+set_no_fast_math_flags ()
+{
+ flag_trapping_math = 1;
+ flag_unsafe_math_optimizations = 0;
+ flag_errno_math = 1;
+}
+
\f
/* Output files for assembler code (real compiler output)
and debugging dumps. */
return log;
}
-/* Return the approximate positive square root of a number N. This is for
- statistical reports, not code generation. */
-double
-approx_sqrt (x)
- double x;
-{
- double s, d;
-
- if (x < 0)
- abort ();
- if (x == 0)
- return 0;
-
- s = x;
- do
- {
- d = (s * s - x) / (2 * s);
- s -= d;
- }
- while (d > .0001);
- return s;
-}
-
static int float_handler_set;
int float_handled;
jmp_buf float_handler;
{
if (float_handled == 0)
crash_signal (signo);
-#if defined (USG) || defined (hpux)
- /* Re-enable the signal catcher. */
- signal (SIGFPE, float_signal);
-#endif
float_handled = 0;
+
+ /* On System-V derived systems, we must reinstall the signal handler.
+ This is harmless on BSD-derived systems. */
signal (SIGFPE, float_signal);
longjmp (float_handler, 1);
}
{
float_handled = (handler != 0);
if (handler)
- bcopy ((char *) handler, (char *) float_handler, sizeof (float_handler));
+ memcpy (float_handler, handler, sizeof (float_handler));
if (float_handled && ! float_handler_set)
{
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 fatal signals, such as SIGSEGV. These are transformed
into ICE messages, which is much more user friendly. */
static void
crash_signal (signo)
- /* If this is missing, some compilers complain. */
int signo;
{
- error ("Internal error: %s.", strsignal (signo));
- finish_abort ();
+ internal_error ("Internal error: %s", strsignal (signo));
}
/* Strip off a legitimate source ending from the input string NAME of
}
}
-/* Given a file name X, return the nondirectory portion. */
-
-char *
-file_name_nondirectory (x)
- const char *x;
-{
- char *tmp = (char *) strrchr (x, '/');
- if (DIR_SEPARATOR != '/' && ! tmp)
- tmp = (char *) strrchr (x, DIR_SEPARATOR);
- if (tmp)
- return (char *) (tmp + 1);
- else
- return (char *) x;
-}
-
/* Output a quoted string. */
void
#endif
}
\f
-#ifdef ASM_IDENTIFY_LANGUAGE
-/* Routine to build language identifier for object file. */
-
-static void
-output_lang_identify (asm_out_file)
- FILE *asm_out_file;
-{
- int len = strlen (lang_identify ()) + sizeof ("__gnu_compiled_") + 1;
- char *s = (char *) alloca (len);
-
- sprintf (s, "__gnu_compiled_%s", lang_identify ());
- ASM_OUTPUT_LABEL (asm_out_file, s);
-}
-#endif
-
/* Routine to open a dump file. Return true if the dump file is enabled. */
static int
rtl_dump_file = fopen (dump_name, open_arg);
if (rtl_dump_file == NULL)
- pfatal_with_name (dump_name);
+ fatal_io_error ("can't open %s", dump_name);
free (dump_name);
defined in a main file, as opposed to an include file. */
if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)
- && (! TREE_READONLY (decl)
- || TREE_PUBLIC (decl)
- || (!optimize
+ && (((! TREE_READONLY (decl) || TREE_PUBLIC (decl))
+ && !DECL_COMDAT (decl))
+ || (!optimize
&& flag_keep_static_consts
&& !DECL_ARTIFICIAL (decl))
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
{
reconsider = 1;
- rest_of_decl_compilation (decl, NULL_PTR, 1, 1);
+ rest_of_decl_compilation (decl, NULL, 1, 1);
}
if (TREE_CODE (decl) == FUNCTION_DECL
/* Cancel the RTL for this decl so that, if debugging info
output for global variables is still to come,
this one will be omitted. */
- DECL_RTL (decl) = NULL;
+ SET_DECL_RTL (decl, NULL_RTX);
/* Warn about any function
declared static but not defined.
input_file_stack = fs->next;
free (fs);
input_file_stack_tick++;
- /* The initial souce file is never popped. */
+ /* The initial source file is never popped. */
if (!input_file_stack)
abort ();
input_filename = input_file_stack->name;
init_timevar ();
timevar_start (TV_TOTAL);
+ /* Open assembler code output file. Do this even if -fsyntax-only is on,
+ because then the driver will have provided the name of a temporary
+ file or bit bucket for us. */
+
+ if (! name_specified && asm_file_name == 0)
+ asm_out_file = stdout;
+ else
+ {
+ if (asm_file_name == 0)
+ {
+ 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
+ asm_out_file = fopen (asm_file_name, "w");
+ if (asm_out_file == 0)
+ fatal_io_error ("can't open %s for writing", asm_file_name);
+ }
+
/* Initialize data in various passes. */
init_obstacks ();
init_regs ();
init_alias_once ();
init_decl_processing ();
+ init_eh ();
init_optabs ();
init_stmt ();
- init_eh ();
init_loop ();
init_reload ();
init_function_once ();
init_stor_layout_once ();
init_varasm_once ();
+ init_EXPR_INSN_LIST_cache ();
/* The following initialization functions need to generate rtl, so
provide a dummy function context for them. */
{
aux_info_file = fopen (aux_info_file_name, "w");
if (aux_info_file == 0)
- pfatal_with_name (aux_info_file_name);
- }
-
- /* Open assembler code output file. Do this even if -fsyntax-only is on,
- because then the driver will have provided the name of a temporary
- file or bit bucket for us. */
-
- if (! name_specified && asm_file_name == 0)
- asm_out_file = stdout;
- else
- {
- if (asm_file_name == 0)
- {
- 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
- asm_out_file = fopen (asm_file_name, "w");
- if (asm_out_file == 0)
- pfatal_with_name (asm_file_name);
+ fatal_io_error ("can't open %s", aux_info_file_name);
}
#ifdef IO_BUFFER_SIZE
/* Perform language-specific initialization.
This may set main_input_filename. */
- lang_init ();
+ if (lang_hooks.init)
+ (*lang_hooks.init) ();
/* If the input doesn't start with a #line, use the input name
as the official input file name. */
fprintf (asm_out_file, "\n");
}
#endif
-
- /* Output something to inform GDB that this compilation was by GCC. */
-#ifndef ASM_IDENTIFY_GCC
- fprintf (asm_out_file, "gcc2_compiled.:\n");
-#else
- ASM_IDENTIFY_GCC (asm_out_file);
-#endif
-
- /* Output something to identify which front-end produced this file. */
-#ifdef ASM_IDENTIFY_LANGUAGE
- ASM_IDENTIFY_LANGUAGE (asm_out_file);
-#endif
} /* ! flag_syntax_only */
#ifndef ASM_OUTPUT_SECTION_NAME
warning ("-ffunction-sections may affect debugging on some targets.");
#endif
- /* ??? 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)
- {
- /* It's best if we can write a nop here since some
- assemblers don't tolerate zeros in the text section. */
- output_asm_insn (get_insn_template (CODE_FOR_nop, NULL), NULL_PTR);
- }
-
/* If dbx symbol table desired, initialize writing it
and output the predefined types. */
timevar_push (TV_SYMOUT);
loop above. */
output_func_start_profiler ();
- /* 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. */
/* Output some stuff at end of file if nec. */
+ dw2_output_indirect_constants ();
+
end_final (dump_base_name);
if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
ASM_FILE_END (asm_out_file);
#endif
+ /* Attach a special .ident directive to the end of the file to identify
+ the version of GCC which compiled this code. The format of the .ident
+ string is patterned after the ones produced by native SVR4 compilers. */
+#ifdef IDENT_ASM_OP
+ if (!flag_no_ident)
+ fprintf (asm_out_file, "%s\"GCC: (GNU) %s\"\n",
+ IDENT_ASM_OP, version_string);
+#endif
+
/* Language-specific end of compilation actions. */
finish_syntax:
- lang_finish ();
+ if (lang_hooks.finish)
+ (*lang_hooks.finish) ();
/* Close the dump files. */
finish_parse ();
- if (ferror (asm_out_file) != 0 || fclose (asm_out_file) != 0)
- fatal_io_error (asm_file_name);
+ if (ferror (asm_out_file) != 0)
+ fatal_io_error ("error writing to %s", asm_file_name);
+ if (fclose (asm_out_file) != 0)
+ fatal_io_error ("error closing %s", asm_file_name);
/* Do whatever is necessary to finish printing the graphs. */
if (graph_dump_format != no_graph)
{
int i;
- for (i = 0; i < DFI_MAX; ++i)
+ for (i = 0; i < (int) DFI_MAX; ++i)
if (dump_file[i].initialized && dump_file[i].graph_dump_p)
{
char seq[16];
|| TREE_CODE (decl) == FUNCTION_DECL)
{
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 (asmspec)
+ make_decl_rtl (decl, asmspec);
+ /* 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 || !DECL_DEFER_OUTPUT (decl))
+ assemble_variable (decl, top_level, at_end, 0);
if (decl == last_assemble_variable_decl)
{
ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
{
if (decode_reg_name (asmspec) >= 0)
{
- DECL_RTL (decl) = 0;
- make_decl_rtl (decl, asmspec, top_level);
+ SET_DECL_RTL (decl, NULL_RTX);
+ make_decl_rtl (decl, asmspec);
}
else
{
error ("invalid register name `%s' for register variable", asmspec);
DECL_REGISTER (decl) = 0;
- make_decl_rtl (decl, NULL, top_level);
+ if (!top_level)
+ expand_decl (decl);
}
}
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_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))
+ if (write_symbols == DWARF_DEBUG
+ && (DECL_INLINE (decl) || DECL_ABSTRACT (decl))
+ && ! DECL_ABSTRACT_ORIGIN (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;
+ int was_abstract = DECL_ABSTRACT (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);
+ if (! was_abstract)
+ set_decl_abstract_flags (decl, 0);
/* Reset CURRENT_FUNCTION_DECL. */
current_function_decl = saved_cfd;
#endif
}
+/* FNDECL is an inline function which is about to be emitted out of line.
+ Do any preparation, such as emitting abstract debug info for the inline
+ before it gets mangled by optimization. */
+
+void
+note_outlining_of_inline_function (fndecl)
+ tree fndecl ATTRIBUTE_UNUSED;
+{
+#ifdef DWARF2_DEBUGGING_INFO
+ /* The DWARF 2 backend tries to reduce debugging bloat by not emitting
+ the abstract description of inline functions until something tries to
+ reference them. Force it out now, before optimizations mangle the
+ block tree. */
+ if (write_symbols == DWARF2_DEBUG)
+ dwarf2out_abstract_function (fndecl);
+#endif
+}
+
/* This is called from finish_function (within yyparse)
after each top-level definition is parsed.
It is supposed to compile that function or variable
}
/* If requested, consider whether to make this function inline. */
- if (DECL_INLINE (decl) || flag_inline_functions)
+ if ((DECL_INLINE (decl) && !flag_no_inline)
+ || flag_inline_functions)
{
timevar_push (TV_INTEGRATION);
lose = function_cannot_inline_p (decl);
close_dump_file (DFI_rtl, print_rtl, insns);
}
+ /* Convert from NOTE_INSN_EH_REGION style notes, and do other
+ sorts of eh initialization. Delay this until after the
+ initial rtl dump so that we can see the original nesting. */
+ convert_from_eh_region_ranges ();
+
/* If function is inline, and we don't yet know whether to
compile it by itself, defer decision till end of compilation.
finish_compilation will call rest_of_compilation again
goto exit_rest_of_compilation;
}
- init_EXPR_INSN_LIST_cache ();
-
ggc_collect ();
/* Initialize some variables used by the optimizers. */
integrate.*/
rtx_equal_function_value_matters = 0;
purge_hard_subreg_sets (get_insns ());
-
+
/* 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;
- /* 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_pop (TV_JUMP);
}
+ /* Complete generation of exception handling code. */
+ find_exception_handler_labels ();
+ if (doing_eh (0))
+ {
+ timevar_push (TV_JUMP);
+ open_dump_file (DFI_eh, decl);
+
+ finish_eh_generation ();
+
+ close_dump_file (DFI_eh, 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.
/* Instantiate all virtual registers. */
instantiate_virtual_regs (current_function_decl, insns);
- /* Find all the EH handlers. */
- find_exception_handler_labels ();
-
open_dump_file (DFI_jump, decl);
/* Always do one jump optimization pass to ensure that JUMP_LABEL fields
if (optimize > 0)
{
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (insns);
+ cleanup_cfg ();
/* ??? Run if-conversion before delete_null_pointer_checks,
since the later does not preserve the CFG. This should
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 we are not running more CSE passes, then we are no longer
+ expecting CSE to be run. But always rerun it in a cheap mode. */
+ cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse;
if (tem || optimize > 1)
{
timevar_push (TV_JUMP);
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (insns);
+ cleanup_cfg ();
delete_null_pointer_checks (insns);
timevar_pop (TV_JUMP);
open_dump_file (DFI_ssa, decl);
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (insns);
+ cleanup_cfg ();
convert_to_ssa ();
close_dump_file (DFI_ssa, print_rtl_with_bb, insns);
insns = get_insns ();
eliminate_dead_code();
-
+
close_dump_file (DFI_dce, print_rtl_with_bb, insns);
timevar_pop (TV_DEAD_CODE_ELIM);
}
if (optimize > 0 && flag_gcse)
{
+ int save_csb, save_cfj;
+ int tem2 = 0;
+
timevar_push (TV_GCSE);
open_dump_file (DFI_gcse, decl);
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (insns);
+ cleanup_cfg ();
tem = gcse_main (insns, rtl_dump_file);
- /* If gcse altered any jumps, rerun jump optimizations to clean
- things up. */
- if (tem)
+ save_csb = flag_cse_skip_blocks;
+ save_cfj = flag_cse_follow_jumps;
+ flag_cse_skip_blocks = flag_cse_follow_jumps = 0;
+
+ /* If -fexpensive-optimizations, re-run CSE to clean up things done
+ by gcse. */
+ if (flag_expensive_optimizations)
+ {
+ timevar_push (TV_CSE);
+ reg_scan (insns, max_reg_num (), 1);
+ tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
+ timevar_pop (TV_CSE);
+ cse_not_expected = !flag_rerun_cse_after_loop;
+ }
+
+ /* If gcse or cse altered any jumps, rerun jump optimizations to clean
+ things up. Then possibly re-run CSE again. */
+ while (tem || tem2)
{
+ tem = tem2 = 0;
timevar_push (TV_JUMP);
jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
!JUMP_AFTER_REGSCAN);
timevar_pop (TV_JUMP);
+
+ if (flag_expensive_optimizations)
+ {
+ timevar_push (TV_CSE);
+ reg_scan (insns, max_reg_num (), 1);
+ tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
+ timevar_pop (TV_CSE);
+ }
}
close_dump_file (DFI_gcse, print_rtl, insns);
timevar_pop (TV_GCSE);
ggc_collect ();
- }
+ flag_cse_skip_blocks = save_csb;
+ flag_cse_follow_jumps = save_cfj;
+ }
/* Move constant computations out of loops. */
??? Rework to not call reg_scan so often. */
timevar_push (TV_JUMP);
+ /* The previous 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 jump work
+ better and possibly speed up compilation. */
+ delete_trivially_dead_insns (insns, max_reg_num ());
+
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);
+ cleanup_cfg ();
if_convert (0);
timevar_pop(TV_IFCVT);
open_dump_file (DFI_cfg, decl);
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (insns);
+ cleanup_cfg ();
check_function_return_warnings ();
close_dump_file (DFI_cfg, print_rtl_with_bb, insns);
flow_loops_find (&loops, LOOP_TREE);
/* Estimate using heuristics if no profiling info is available. */
- estimate_probability (&loops);
+ if (flag_guess_branch_prob)
+ estimate_probability (&loops);
if (rtl_dump_file)
flow_loops_dump (&loops, rtl_dump_file, NULL, 0);
timevar_push (TV_FLOW);
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (insns);
+ cleanup_cfg ();
/* Blimey. We've got to have the CFG up to date for the call to
if_convert below. However, the random deletion of blocks
#ifdef OPTIMIZE_MODE_SWITCHING
timevar_push (TV_GCSE);
- if (optimize_mode_switching (NULL_PTR))
+ if (optimize_mode_switching (NULL))
{
/* We did work, and so had to regenerate global life information.
Take advantage of this and don't re-recompute register life
}
/* If optimizing, then go ahead and split insns now since we are about
- to recompute flow information anyway. */
+ to recompute flow information anyway. Since we can't split insns after
+ reload, do the splitting unconditionally here to avoid gcc from losing
+ REG_DEAD notes. */
+#ifdef STACK_REGS
+ if (1)
+#else
if (optimize > 0)
+#endif
{
int old_labelnum = max_label_num ();
if (optimize)
{
- cleanup_cfg (insns);
+ cleanup_cfg ();
life_analysis (insns, rtl_dump_file, PROP_FINAL);
/* This is kind of a heuristic. We need to run combine_stack_adjustments
/* CFG no longer kept up to date. */
- close_dump_file (DFI_jump2, print_rtl_with_bb, insns);
+ close_dump_file (DFI_jump2, print_rtl, insns);
timevar_pop (TV_JUMP);
}
MACHINE_DEPENDENT_REORG (insns);
- close_dump_file (DFI_mach, print_rtl_with_bb, insns);
+ close_dump_file (DFI_mach, print_rtl, insns);
ggc_collect ();
#endif
dbr_schedule (insns, rtl_dump_file);
- close_dump_file (DFI_dbr, print_rtl_with_bb, insns);
+ close_dump_file (DFI_dbr, print_rtl, insns);
timevar_pop (TV_DBR_SCHED);
ggc_collect ();
}
#endif
+#ifndef STACK_REGS
+ /* ??? Do this before shorten branches so that we aren't creating
+ insns too late and fail sanity checks in final. */
+ convert_to_eh_region_ranges ();
+#endif
+
/* Shorten branches.
Note this must run before reg-stack because of death note (ab)use
reg_to_stack (insns, rtl_dump_file);
- close_dump_file (DFI_stack, print_rtl_with_bb, insns);
+ close_dump_file (DFI_stack, print_rtl, insns);
timevar_pop (TV_REG_STACK);
ggc_collect ();
+
+ convert_to_eh_region_ranges ();
#endif
current_function_nothrow = nothrow_function_p ();
final_start_function (insns, asm_out_file, optimize);
final (insns, asm_out_file, optimize, 0);
final_end_function (insns, asm_out_file, optimize);
+
+#ifdef IA64_UNWIND_INFO
+ /* ??? The IA-64 ".handlerdata" directive must be issued before
+ the ".endp" directive that closes the procedure descriptor. */
+ output_function_exception_table ();
+#endif
+
assemble_end_function (decl, fnname);
+
+#ifndef IA64_UNWIND_INFO
+ /* Otherwise, it feels unclean to switch sections in the middle. */
+ output_function_exception_table ();
+#endif
+
if (! quiet_flag)
fflush (asm_out_file);
printf (_(" -O[number] Set optimisation level to [number]\n"));
printf (_(" -Os Optimise for space rather than speed\n"));
+ for (i = sizeof (compiler_params); i--;)
+ {
+ const char *description = compiler_params[i].help;
+ const int length = 21-strlen(compiler_params[i].option);
+
+ if (description != NULL && * description != 0)
+ printf (" --param %s=<value>%.*s%s\n",
+ compiler_params[i].option,
+ length > 0 ? length : 1, " ",
+ description);
+ }
printf (_(" -pedantic Issue warnings needed by strict compliance to ISO C\n"));
printf (_(" -pedantic-errors Like -pedantic except that errors are produced\n"));
printf (_(" -w Suppress warnings\n"));
switch (c = *arg++)
{
case 'a':
- for (i = 0; i < DFI_MAX; ++i)
+ for (i = 0; i < (int) DFI_MAX; ++i)
dump_file[i].enabled = 1;
break;
case 'A':
flag_debug_asm = 1;
break;
- case 'm':
- flag_print_mem = 1;
- break;
case 'p':
flag_print_asm_name = 1;
break;
default:
matched = 0;
- for (i = 0; i < DFI_MAX; ++i)
+ for (i = 0; i < (int) DFI_MAX; ++i)
if (c == dump_file[i].debug_switch)
{
dump_file[i].enabled = 1;
}
}
- if ((option_value = skip_leading_substring (arg, "inline-limit-"))
- || (option_value = skip_leading_substring (arg, "inline-limit=")))
- inline_max_insns =
- read_integral_parameter (option_value, arg - 2, inline_max_insns);
+ if (!strcmp (arg, "fast-math"))
+ set_fast_math_flags();
+ else if (!strcmp (arg, "no-fast-math"))
+ set_no_fast_math_flags();
+ else if ((option_value = skip_leading_substring (arg, "inline-limit-"))
+ || (option_value = skip_leading_substring (arg, "inline-limit=")))
+ {
+ int val =
+ read_integral_parameter (option_value, arg - 2,
+ MAX_INLINE_INSNS);
+ set_param_value ("max-inline-insns", val);
+ }
#ifdef INSN_SCHEDULING
else if ((option_value = skip_leading_substring (arg, "sched-verbose=")))
fix_sched_param ("verbose", option_value);
{
larger_than_size = read_integral_parameter (option_value, arg - 2, -1);
- if (larger_than_size != -1)
- warn_larger_than = 1;
+ warn_larger_than = larger_than_size != -1;
}
else if (!strcmp (arg, "unused"))
{
if (!strcmp (arg, "-help"))
{
display_help ();
- exit (0);
+ exit_after_options = 1;
}
if (!strcmp (arg, "-target-help"))
{
display_target_options ();
- exit (0);
+ exit_after_options = 1;
+ }
+
+ if (!strcmp (arg, "-version"))
+ {
+ print_version (stderr, "");
+ exit_after_options = 1;
+ }
+
+ /* Handle '--param <name>=<value>'. */
+ if (strcmp (arg, "-param") == 0)
+ {
+ char *equal;
+
+ if (argc == 1)
+ {
+ error ("-param option missing argument");
+ return 1;
+ }
+
+ /* Get the '<name>=<value>' parameter. */
+ arg = argv[1];
+ /* Look for the `='. */
+ equal = strchr (arg, '=');
+ if (!equal)
+ error ("invalid --param option: %s", arg);
+ else
+ {
+ int val;
+
+ /* Zero out the `=' sign so that we get two separate strings. */
+ *equal = '\0';
+ /* Figure out what value is specified. */
+ val = read_integral_parameter (equal + 1, NULL, INVALID_PARAM_VAL);
+ if (val != INVALID_PARAM_VAL)
+ set_param_value (arg, val);
+ else
+ error ("invalid parameter value `%s'", equal + 1);
+ }
+
+ return 2;
}
if (*arg == 'Y')
return 1;
}
\f
-/* Entry point of cc1/c++. Decode command args, then call compile_file.
- Exit code is 35 if can't open files, 34 if fatal error,
- 33 if had nonfatal errors, else success. */
+/* Entry point of cc1, cc1plus, jc1, f771, etc.
+ Decode command args, then call compile_file.
+ Exit code is FATAL_EXIT_CODE if can't open files or if there were
+ any errors, or SUCCESS_EXIT_CODE if compilation succeeded.
-extern int main PARAMS ((int, char **));
+ It is not safe to call this function more than once. */
int
-main (argc, argv)
+toplev_main (argc, argv)
int argc;
char **argv;
{
--p;
progname = p;
+ xmalloc_set_program_name (progname);
+
+/* LC_CTYPE determines the character set used by the terminal so it has be set
+ to output messages correctly. */
+
#ifdef HAVE_LC_MESSAGES
+ setlocale (LC_CTYPE, "");
setlocale (LC_MESSAGES, "");
+#else
+ setlocale (LC_ALL, "");
#endif
+
(void) bindtextdomain (PACKAGE, localedir);
(void) textdomain (PACKAGE);
/* Initialize the diagnostics reporting machinery. */
initialize_diagnostics ();
+ /* Register the language-independent parameters. */
+ add_params (lang_independent_params, LAST_PARAM);
+
/* Perform language-specific options intialization. */
- lang_init_options ();
+ if (lang_hooks.init_options)
+ (*lang_hooks.init_options) ();
/* Scan to see what optimization level has been specified. That will
determine the default value of many flags. */
#ifdef CAN_DEBUG_WITHOUT_FP
flag_omit_frame_pointer = 1;
#endif
+ flag_guess_branch_prob = 1;
}
if (optimize >= 2)
/* Perform normal command line switch decoding. */
for (i = 1; i < argc;)
{
- unsigned int lang_processed;
- unsigned int indep_processed;
+ int lang_processed;
+ int indep_processed;
/* Give the language a chance to decode the option for itself. */
- lang_processed = lang_decode_option (argc - i, argv + i);
+ lang_processed = (*lang_hooks.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. */
- indep_processed = independent_decode_option (argc - i, argv + i);
+ if (lang_processed >= 0)
+ /* Now see if the option also has a language independent meaning.
+ Some options are both language specific and language independent,
+ eg --help. */
+ indep_processed = independent_decode_option (argc - i, argv + i);
+ else
+ {
+ lang_processed = -lang_processed;
+ indep_processed = 0;
+ }
if (lang_processed || indep_processed)
i += MAX (lang_processed, indep_processed);
}
}
+ /* All command line options have been processed. */
+ if (lang_hooks.post_options)
+ (*lang_hooks.post_options) ();
+
+ if (exit_after_options)
+ exit (0);
+
/* Reflect any language-specific diagnostic option setting. */
reshape_diagnostic_buffer ();
flag_no_inline = 1;
warn_inline = 0;
- /* The c_decode_option and lang_decode_option functions set
+ /* The c_decode_option function and decode_option hook set
this to `2' if -Wall is used, so we can avoid giving out
lots of errors for people who don't realize what -Wall does. */
if (warn_uninitialized == 1)
OVERRIDE_OPTIONS;
#endif
- if (exceptions_via_longjmp == 2)
- {
-#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;
warning ("this target machine does not have delayed branches");
#endif
+ /* Some operating systems do not allow profiling without a frame
+ pointer. */
+ if (!TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
+ && profile_flag
+ && flag_omit_frame_pointer)
+ {
+ error ("profiling does not work without a frame pointer");
+ flag_omit_frame_pointer = 0;
+ }
+
user_label_prefix = USER_LABEL_PREFIX;
if (flag_leading_underscore != -1)
{
compile_file (filename);
-#if !defined(OS2) && !defined(VMS) && (!defined(_WIN32) || defined (__CYGWIN__)) && !defined(__INTERIX)
- if (flag_print_mem)
- {
- char *lim = (char *) sbrk (0);
-
- fnotice (stderr, "Data size %ld.\n", (long) (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 || CYGWIN) && ! __INTERIX */
-
if (errorcount)
return (FATAL_EXIT_CODE);
if (sorrycount)
#endif
fnotice (file,
#ifdef __GNUC__
- "%s%s%s version %s (%s) compiled by GNU C version %s.\n"
+ "%s%s%s version %s (%s)\n%s\tcompiled by GNU C version %s.\n"
#else
"%s%s%s version %s (%s) compiled by CC.\n"
#endif
, indent, *indent != 0 ? " " : "",
- language_string, version_string, TARGET_NAME, __VERSION__);
+ language_string, version_string, TARGET_NAME,
+ indent, __VERSION__);
}
/* Print an option value and return the adjusted position in the line.
#endif
}
-/* Called from check_newline in c-parse.y. The `buffer' parameter contains
+/* Called from cb_define in c-lex.c. The `buffer' parameter contains
the tail part of the directive line, i.e. the part which is past the
initial whitespace, #, whitespace, directive-name, whitespace part. */
void
debug_define (lineno, buffer)
register unsigned lineno ATTRIBUTE_UNUSED;
- register char *buffer ATTRIBUTE_UNUSED;
+ register const char *buffer ATTRIBUTE_UNUSED;
{
#ifdef DWARF_DEBUGGING_INFO
- if (debug_info_level == DINFO_LEVEL_VERBOSE
- && write_symbols == DWARF_DEBUG)
+ if (write_symbols == DWARF_DEBUG)
dwarfout_define (lineno, buffer);
#endif /* DWARF_DEBUGGING_INFO */
#ifdef DWARF2_DEBUGGING_INFO
- if (debug_info_level == DINFO_LEVEL_VERBOSE
- && write_symbols == DWARF2_DEBUG)
+ if (write_symbols == DWARF2_DEBUG)
dwarf2out_define (lineno, buffer);
#endif /* DWARF2_DEBUGGING_INFO */
}
-/* Called from check_newline in c-parse.y. The `buffer' parameter contains
+/* Called from cb_undef in c-lex.c. The `buffer' parameter contains
the tail part of the directive line, i.e. the part which is past the
initial whitespace, #, whitespace, directive-name, whitespace part. */
void
debug_undef (lineno, buffer)
register unsigned lineno ATTRIBUTE_UNUSED;
- register char *buffer ATTRIBUTE_UNUSED;
+ register const char *buffer ATTRIBUTE_UNUSED;
{
#ifdef DWARF_DEBUGGING_INFO
- if (debug_info_level == DINFO_LEVEL_VERBOSE
- && write_symbols == DWARF_DEBUG)
+ if (write_symbols == DWARF_DEBUG)
dwarfout_undef (lineno, buffer);
#endif /* DWARF_DEBUGGING_INFO */
#ifdef DWARF2_DEBUGGING_INFO
- if (debug_info_level == DINFO_LEVEL_VERBOSE
- && write_symbols == DWARF2_DEBUG)
+ if (write_symbols == DWARF2_DEBUG)
dwarf2out_undef (lineno, buffer);
#endif /* DWARF2_DEBUGGING_INFO */
}