X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftoplev.c;h=425f94ea6af7f2230d26d62488e5a67b6e1c784c;hb=08d163a9f560aba0131e1ec71cc5de397c8579fb;hp=3bf601113a9cb6eb710fba6ffe710f293585addd;hpb=344c9292b91c43a6e46e680d935c703fb0c88c90;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/toplev.c b/gcc/toplev.c index 3bf601113a9..425f94ea6af 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1,6 +1,6 @@ /* Top level of GCC compilers (cc1, cc1plus, etc.) Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -63,7 +63,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "regs.h" #include "timevar.h" #include "diagnostic.h" -#include "ssa.h" #include "params.h" #include "reload.h" #include "dwarf2asm.h" @@ -78,6 +77,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "cgraph.h" #include "opts.h" #include "coverage.h" +#include "value-prof.h" #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO) #include "dwarf2out.h" @@ -96,6 +96,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA declarations for e.g. AIX 4.x. */ #endif +#ifndef HAVE_conditional_execution +#define HAVE_conditional_execution 0 +#endif + /* Carry information from ASM_DECLARE_OBJECT_NAME to ASM_FINISH_DECLARE_OBJECT. */ @@ -124,7 +128,6 @@ static void print_switch_values (FILE *, int, int, const char *, /* Rest of compilation helper functions. */ static bool rest_of_handle_inlining (tree); -static rtx rest_of_handle_ssa (tree, rtx); static void rest_of_handle_cse (tree, rtx); static void rest_of_handle_cse2 (tree, rtx); static void rest_of_handle_gcse (tree, rtx); @@ -137,6 +140,7 @@ static void rest_of_handle_null_pointer (tree, rtx); static void rest_of_handle_addressof (tree, rtx); static void rest_of_handle_cfg (tree, rtx); static void rest_of_handle_branch_prob (tree, rtx); +static void rest_of_handle_value_profile_transformations (tree, rtx); static void rest_of_handle_if_conversion (tree, rtx); static void rest_of_handle_if_after_combine (tree, rtx); static void rest_of_handle_tracer (tree, rtx); @@ -146,8 +150,8 @@ static void rest_of_handle_regmove (tree, rtx); static void rest_of_handle_sched (tree, rtx); static void rest_of_handle_sched2 (tree, rtx); #endif -static bool rest_of_handle_new_regalloc (tree, rtx, int *); -static bool rest_of_handle_old_regalloc (tree, rtx, int *); +static bool rest_of_handle_new_regalloc (tree, rtx); +static bool rest_of_handle_old_regalloc (tree, rtx); static void rest_of_handle_regrename (tree, rtx); static void rest_of_handle_reorder_blocks (tree, rtx); #ifdef STACK_REGS @@ -185,6 +189,8 @@ const char *main_input_filename; location_t input_location; +struct line_maps line_table; + /* Nonzero if it is unsafe to create any new pseudo registers. */ int no_new_pseudos; @@ -221,7 +227,7 @@ int target_flags_explicit; /* Debug hooks - dependent upon command line options. */ -const struct gcc_debug_hooks *debug_hooks = &do_nothing_debug_hooks; +const struct gcc_debug_hooks *debug_hooks; /* Describes a dump file. */ @@ -252,10 +258,6 @@ enum dump_file_index DFI_sibling, DFI_eh, DFI_jump, - DFI_ssa, - DFI_ssa_ccp, - DFI_ssa_dce, - DFI_ussa, DFI_null, DFI_cse, DFI_addressof, @@ -264,9 +266,11 @@ enum dump_file_index DFI_bypass, DFI_cfg, DFI_bp, + DFI_vpt, DFI_ce1, DFI_tracer, DFI_loop2, + DFI_web, DFI_cse2, DFI_life, DFI_combine, @@ -279,8 +283,8 @@ enum dump_file_index DFI_flow2, DFI_peephole2, DFI_rnreg, - DFI_bbro, DFI_ce3, + DFI_bbro, DFI_branch_target_load, DFI_sched2, DFI_stack, @@ -294,8 +298,8 @@ enum dump_file_index Remaining -d letters: - " m q " - " JK O Q V YZ" + " e m q " + " JK O Q WXY " */ static struct dump_file_info dump_file[DFI_MAX] = @@ -305,10 +309,6 @@ static struct dump_file_info dump_file[DFI_MAX] = { "sibling", 'i', 0, 0, 0 }, { "eh", 'h', 0, 0, 0 }, { "jump", 'j', 0, 0, 0 }, - { "ssa", 'e', 1, 0, 0 }, - { "ssaccp", 'W', 1, 0, 0 }, - { "ssadce", 'X', 1, 0, 0 }, - { "ussa", 'e', 1, 0, 0 }, /* Yes, duplicate enable switch. */ { "null", 'u', 0, 0, 0 }, { "cse", 's', 0, 0, 0 }, { "addressof", 'F', 0, 0, 0 }, @@ -317,9 +317,11 @@ static struct dump_file_info dump_file[DFI_MAX] = { "bypass", 'G', 1, 0, 0 }, /* Yes, duplicate enable switch. */ { "cfg", 'f', 1, 0, 0 }, { "bp", 'b', 1, 0, 0 }, + { "vpt", 'V', 1, 0, 0 }, { "ce1", 'C', 1, 0, 0 }, { "tracer", 'T', 1, 0, 0 }, { "loop2", 'L', 1, 0, 0 }, + { "web", 'Z', 0, 0, 0 }, { "cse2", 't', 1, 0, 0 }, { "life", 'f', 1, 0, 0 }, /* Yes, duplicate enable switch. */ { "combine", 'c', 1, 0, 0 }, @@ -332,8 +334,8 @@ static struct dump_file_info dump_file[DFI_MAX] = { "flow2", 'w', 1, 0, 0 }, { "peephole2", 'z', 1, 0, 0 }, { "rnreg", 'n', 1, 0, 0 }, - { "bbro", 'B', 1, 0, 0 }, { "ce3", 'E', 1, 0, 0 }, + { "bbro", 'B', 1, 0, 0 }, { "btl", 'd', 1, 0, 0 }, /* Yes, duplicate enable switch. */ { "sched2", 'R', 1, 0, 0 }, { "stack", 'k', 1, 0, 0 }, @@ -355,21 +357,6 @@ enum graph_dump_types graph_dump_format; const char *asm_file_name; -/* Type(s) of debugging information we are producing (if any). - See flags.h for the definitions of the different possible - types of debugging information. */ -enum debug_info_type write_symbols = NO_DEBUG; - -/* Level of debugging information we are producing. See flags.h - for the definitions of the different possible levels. */ -enum debug_info_level debug_info_level = DINFO_LEVEL_NONE; - -/* Nonzero means use GNU-only extensions in the generated symbolic - debugging information. */ -/* Currently, this only has an effect when write_symbols is set to - DBX_DEBUG, XCOFF_DEBUG, or DWARF_DEBUG. */ -int use_gnu_debug_info_extensions = 0; - /* Nonzero means do optimizations. -O. Particular numeric values stand for particular amounts of optimization; thus, -O2 stores 2 here. However, the optimizations beyond the basic @@ -417,6 +404,9 @@ int profile_arc_flag = 0; int flag_profile_values = 0; +/* Nonzero if value histograms should be used to optimize code. */ +int flag_value_profile_transformations = 0; + /* Nonzero if generating info for gcov to calculate line test coverage. */ int flag_test_coverage = 0; @@ -487,11 +477,7 @@ int flag_short_enums; be saved across function calls, if that produces overall better code. Optional now, so people can test it. */ -#ifdef DEFAULT_CALLER_SAVES -int flag_caller_saves = 1; -#else int flag_caller_saves = 0; -#endif /* Nonzero if structures and unions should be returned in memory. @@ -648,6 +634,11 @@ int flag_finite_math_only = 0; int flag_trapping_math = 1; +/* Nonzero means disable transformations that assume default floating + point rounding behavior. */ + +int flag_rounding_math = 0; + /* Nonzero means disable transformations observable by signaling NaNs. This option implies that any operation on an IEEE signaling NaN can generate a (user-visible) trap. */ @@ -664,6 +655,10 @@ int flag_complex_divide_method = 0; int flag_syntax_only = 0; +/* Nonzero means performs web construction pass. */ + +int flag_web; + /* Nonzero means perform loop optimizer. */ int flag_loop_optimize; @@ -701,6 +696,11 @@ int flag_gcse_lm = 1; int flag_gcse_sm = 1; +/* Nonzero if we want to perfrom redundant load after store elimination + in gcse. */ + +int flag_gcse_las = 1; + /* Perform target register optimization before prologue / epilogue threading. */ @@ -711,6 +711,11 @@ int flag_branch_target_load_optimize = 0; int flag_branch_target_load_optimize2 = 0; +/* For the bt-load pass, nonzero means don't re-use branch target registers + in any basic block. */ + +int flag_btr_bb_exclusive; + /* Nonzero means to rerun cse after loop optimization. This increases compilation time about 20% and picks up a few more common expressions. */ @@ -836,6 +841,20 @@ int flag_schedule_speculative = 1; int flag_schedule_speculative_load = 0; int flag_schedule_speculative_load_dangerous = 0; +/* The following flags have an effect during scheduling after register + allocation: + + flag_sched_stalled_insns means that insns can be moved prematurely from the queue + of stalled insns into the ready list. + + flag_sched_stalled_insns_dep controls how many insn groups will be examined + for a dependency on a stalled insn that is candidate for premature removal + from the queue of stalled insns into the ready list (has an effect only if + the flag 'sched_stalled_insns' is set). */ + +int flag_sched_stalled_insns = 0; +int flag_sched_stalled_insns_dep = 1; + int flag_single_precision_constant; /* flag_branch_on_count_reg means try to replace add-1,compare,branch tupple @@ -870,27 +889,9 @@ int flag_debug_asm = 0; int flag_dump_rtl_in_asm = 0; -/* -fgnu-linker specifies use of the GNU linker for initializations. - (Or, more generally, a linker that handles initializations.) - -fno-gnu-linker says that collect2 will be used. */ -#ifdef USE_COLLECT2 -int flag_gnu_linker = 0; -#else -int flag_gnu_linker = 1; -#endif - /* Nonzero means put zero initialized data in the bss section. */ int flag_zero_initialized_in_bss = 1; -/* Enable SSA. */ -int flag_ssa = 0; - -/* Enable ssa conditional constant propagation. */ -int flag_ssa_ccp = 0; - -/* Enable ssa aggressive dead code elimination. */ -int flag_ssa_dce = 0; - /* Tag all structures with __attribute__(packed). */ int flag_pack_struct = 0; @@ -984,46 +985,6 @@ int align_functions_log; minimum function alignment. Zero means no alignment is forced. */ int force_align_functions_log; -/* Table of supported debugging formats. */ -static const struct -{ - const char *const arg; - /* Since PREFERRED_DEBUGGING_TYPE isn't necessarily a - constant expression, we use NO_DEBUG in its place. */ - const enum debug_info_type debug_type; - const int use_extensions_p; - const char *const description; -} *da, -debug_args[] = -{ - { "", NO_DEBUG, DEFAULT_GDB_EXTENSIONS, - N_("Generate debugging info in default format") }, - { "gdb", NO_DEBUG, 1, N_("Generate debugging info in default extended format") }, -#ifdef DBX_DEBUGGING_INFO - { "stabs", DBX_DEBUG, 0, N_("Generate STABS format debug info") }, - { "stabs+", DBX_DEBUG, 1, N_("Generate extended STABS format debug info") }, -#endif -#ifdef DWARF_DEBUGGING_INFO - { "dwarf", DWARF_DEBUG, 0, N_("Generate DWARF-1 format debug info") }, - { "dwarf+", DWARF_DEBUG, 1, - N_("Generate extended DWARF-1 format debug info") }, -#endif -#ifdef DWARF2_DEBUGGING_INFO - { "dwarf-2", DWARF2_DEBUG, 0, N_("Generate DWARF-2 debug info") }, -#endif -#ifdef XCOFF_DEBUGGING_INFO - { "xcoff", XCOFF_DEBUG, 0, N_("Generate XCOFF format debug info") }, - { "xcoff+", XCOFF_DEBUG, 1, N_("Generate extended XCOFF format debug info") }, -#endif -#ifdef SDB_DEBUGGING_INFO - { "coff", SDB_DEBUG, 0, N_("Generate COFF format debug info") }, -#endif -#ifdef VMS_DEBUGGING_INFO - { "vms", VMS_DEBUG, 0, N_("Generate VMS format debug info") }, -#endif - { 0, 0, 0, 0 } -}; - typedef struct { const char *const string; @@ -1038,6 +999,9 @@ int flag_trapv = 0; /* Nonzero if signed arithmetic overflow should wrap around. */ int flag_wrapv = 0; +/* Nonzero if subexpressions must be evaluated from left-to-right. */ +int flag_evaluation_order = 0; + /* Add or remove a leading underscore from user symbols. */ int flag_leading_underscore = -1; @@ -1098,11 +1062,14 @@ static const lang_independent_options f_options[] = {"pcc-struct-return", &flag_pcc_struct_return, 1 }, {"reg-struct-return", &flag_pcc_struct_return, 0 }, {"delayed-branch", &flag_delayed_branch, 1 }, + {"web", &flag_web, 1}, {"gcse", &flag_gcse, 1 }, {"gcse-lm", &flag_gcse_lm, 1 }, {"gcse-sm", &flag_gcse_sm, 1 }, + {"gcse-las", &flag_gcse_las, 1 }, {"branch-target-load-optimize", &flag_branch_target_load_optimize, 1 }, {"branch-target-load-optimize2", &flag_branch_target_load_optimize2, 1 }, + {"btr-bb-exclusive", &flag_btr_bb_exclusive, 1 }, {"loop-optimize", &flag_loop_optimize, 1 }, {"crossjumping", &flag_crossjumping, 1 }, {"if-conversion", &flag_if_conversion, 1 }, @@ -1116,6 +1083,8 @@ static const lang_independent_options f_options[] = {"sched-spec",&flag_schedule_speculative, 1 }, {"sched-spec-load",&flag_schedule_speculative_load, 1 }, {"sched-spec-load-dangerous",&flag_schedule_speculative_load_dangerous, 1 }, + {"sched-stalled-insns", &flag_sched_stalled_insns, 0 }, + {"sched-stalled-insns-dep", &flag_sched_stalled_insns_dep, 1 }, {"sched2-use-superblocks", &flag_sched2_use_superblocks, 1 }, {"sched2-use-traces", &flag_sched2_use_traces, 1 }, {"branch-count-reg",&flag_branch_on_count_reg, 1 }, @@ -1128,6 +1097,8 @@ static const lang_independent_options f_options[] = {"asynchronous-unwind-tables", &flag_asynchronous_unwind_tables, 1 }, {"non-call-exceptions", &flag_non_call_exceptions, 1 }, {"profile-arcs", &profile_arc_flag, 1 }, + {"profile-values", &flag_profile_values, 1 }, + {"vpt", &flag_value_profile_transformations, 1 }, {"test-coverage", &flag_test_coverage, 1 }, {"branch-probabilities", &flag_branch_probabilities, 1 }, {"profile", &profile_flag, 1 }, @@ -1140,7 +1111,6 @@ static const lang_independent_options f_options[] = {"function-sections", &flag_function_sections, 1 }, {"data-sections", &flag_data_sections, 1 }, {"verbose-asm", &flag_verbose_asm, 1 }, - {"gnu-linker", &flag_gnu_linker, 1 }, {"regmove", &flag_regmove, 1 }, {"optimize-register-move", &flag_regmove, 1 }, {"pack-struct", &flag_pack_struct, 1 }, @@ -1158,9 +1128,6 @@ static const lang_independent_options f_options[] = {"dump-unnumbered", &flag_dump_unnumbered, 1 }, {"instrument-functions", &flag_instrument_function_entry_exit, 1 }, {"zero-initialized-in-bss", &flag_zero_initialized_in_bss, 1 }, - {"ssa", &flag_ssa, 1 }, - {"ssa-ccp", &flag_ssa_ccp, 1 }, - {"ssa-dce", &flag_ssa_dce, 1 }, {"leading-underscore", &flag_leading_underscore, 1 }, {"ident", &flag_no_ident, 0 }, { "peephole2", &flag_peephole2, 1 }, @@ -1168,6 +1135,7 @@ static const lang_independent_options f_options[] = { "guess-branch-probability", &flag_guess_branch_prob, 1 }, {"math-errno", &flag_errno_math, 1 }, {"trapping-math", &flag_trapping_math, 1 }, + {"rounding-math", &flag_rounding_math, 1 }, {"unsafe-math-optimizations", &flag_unsafe_math_optimizations, 1 }, {"signaling-nans", &flag_signaling_nans, 1 }, {"bounds-check", &flag_bounds_check, 1 }, @@ -1219,6 +1187,58 @@ FILE *aux_info_file; FILE *rtl_dump_file = NULL; FILE *cgraph_dump_file = NULL; +/* The current working directory of a translation. It's generally the + directory from which compilation was initiated, but a preprocessed + file may specify the original directory in which it was + created. */ + +static const char *src_pwd; + +/* Initialize src_pwd with the given string, and return true. If it + was already initialized, return false. As a special case, it may + be called with a NULL argument to test whether src_pwd has NOT been + initialized yet. */ + +bool +set_src_pwd (const char *pwd) +{ + if (src_pwd) + return false; + + src_pwd = xstrdup (pwd); + return true; +} + +/* Return the directory from which the translation unit was initiated, + in case set_src_pwd() was not called before to assign it a + different value. */ + +const char * +get_src_pwd (void) +{ + if (! src_pwd) + src_pwd = getpwd (); + + return src_pwd; +} + +/* Called when the start of a function definition is parsed, + this function prints on stderr the name of the function. */ +void +announce_function (tree decl) +{ + if (!quiet_flag) + { + if (rtl_dump_and_exit) + verbatim ("%s ", IDENTIFIER_POINTER (DECL_NAME (decl))); + else + verbatim (" %s", (*lang_hooks.decl_printable_name) (decl, 2)); + fflush (stderr); + pp_needs_newline (global_dc->printer) = true; + diagnostic_set_last_function (global_dc); + } +} + /* Set up a default flag_random_seed and local_tick, unless the user already specified one. */ @@ -1229,12 +1249,12 @@ randomize (void) { unsigned HOST_WIDE_INT value; static char random_seed[HOST_BITS_PER_WIDE_INT / 4 + 3]; - + /* Get some more or less random data. */ #ifdef HAVE_GETTIMEOFDAY { struct timeval tv; - + gettimeofday (&tv, NULL); local_tick = tv.tv_sec * 1000 + tv.tv_usec / 1000; } @@ -1247,7 +1267,7 @@ randomize (void) } #endif value = local_tick ^ getpid (); - + sprintf (random_seed, HOST_WIDE_INT_PRINT_HEX, value); flag_random_seed = random_seed; } @@ -1400,8 +1420,14 @@ output_quoted_string (FILE *asm_file, const char *string) void output_file_directive (FILE *asm_file, const char *input_name) { - int len = strlen (input_name); - const char *na = input_name + len; + int len; + const char *na; + + if (input_name == NULL) + input_name = ""; + + len = strlen (input_name); + na = input_name + len; /* NA gets INPUT_NAME sans directory names. */ while (na > input_name) @@ -1411,9 +1437,6 @@ output_file_directive (FILE *asm_file, const char *input_name) na--; } -#ifdef ASM_OUTPUT_MAIN_SOURCE_FILENAME - ASM_OUTPUT_MAIN_SOURCE_FILENAME (asm_file, na); -#else #ifdef ASM_OUTPUT_SOURCE_FILENAME ASM_OUTPUT_SOURCE_FILENAME (asm_file, na); #else @@ -1421,7 +1444,6 @@ output_file_directive (FILE *asm_file, const char *input_name) output_quoted_string (asm_file, na); fputc ('\n', asm_file); #endif -#endif } /* Routine to open a dump file. Return true if the dump file is enabled. */ @@ -1585,7 +1607,7 @@ wrapup_global_declarations (tree *vec, int len) if (flag_unit_at_a_time && cgraph_varpool_node (decl)->finalized) needed = 0; - else if (flag_unit_at_a_time + else if ((flag_unit_at_a_time && !cgraph_global_info_ready) && (TREE_USED (decl) || TREE_USED (DECL_ASSEMBLER_NAME (decl)))) /* needed */; @@ -1608,6 +1630,7 @@ wrapup_global_declarations (tree *vec, int len) if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) != 0 && DECL_SAVED_INSNS (decl) != 0 + && DECL_SAVED_INSNS (decl)->saved_for_inline && (flag_keep_inline_functions || (TREE_PUBLIC (decl) && !DECL_COMDAT (decl)) || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))) @@ -1659,11 +1682,9 @@ check_global_declarations (tree *vec, int len) && ! TREE_PUBLIC (decl)) { if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) - pedwarn_with_decl (decl, - "`%s' used but never defined"); + pedwarn ("%J'%F' used but never defined", decl, decl); else - warning_with_decl (decl, - "`%s' declared `static' but never defined"); + warning ("%J'%F' declared `static' but never defined", decl, decl); /* This symbol is effectively an "extern" declaration now. */ TREE_PUBLIC (decl) = 1; assemble_external (decl); @@ -1671,7 +1692,11 @@ check_global_declarations (tree *vec, int len) /* Warn about static fns or vars defined but not used. */ if (((warn_unused_function && TREE_CODE (decl) == FUNCTION_DECL) - || (warn_unused_variable && TREE_CODE (decl) == VAR_DECL)) + /* We don't warn about "static const" variables because the + "rcs_id" idiom uses that construction. */ + || (warn_unused_variable + && TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl))) + && ! DECL_IN_SYSTEM_HEADER (decl) && ! TREE_USED (decl) /* The TREE_USED bit for file-scope decls is kept in the identifier, to handle multiple external decls in different scopes. */ @@ -1684,7 +1709,7 @@ check_global_declarations (tree *vec, int len) && ! (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl)) /* Otherwise, ask the language. */ && (*lang_hooks.decls.warn_unused_global) (decl)) - warning_with_decl (decl, "`%s' defined but not used"); + warning ("%J'%D' defined but not used", decl, decl); /* Avoid confusing the debug information machinery when there are errors. */ @@ -1697,6 +1722,44 @@ check_global_declarations (tree *vec, int len) } } +/* Warn about a use of an identifier which was marked deprecated. */ +void +warn_deprecated_use (tree node) +{ + if (node == 0 || !warn_deprecated_decl) + return; + + if (DECL_P (node)) + warning ("`%s' is deprecated (declared at %s:%d)", + IDENTIFIER_POINTER (DECL_NAME (node)), + DECL_SOURCE_FILE (node), DECL_SOURCE_LINE (node)); + else if (TYPE_P (node)) + { + const char *what = NULL; + tree decl = TYPE_STUB_DECL (node); + + if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE) + what = IDENTIFIER_POINTER (TYPE_NAME (node)); + else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL + && DECL_NAME (TYPE_NAME (node))) + what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node))); + + if (what) + { + if (decl) + warning ("`%s' is deprecated (declared at %s:%d)", what, + DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); + else + warning ("`%s' is deprecated", what); + } + else if (decl) + warning ("type is deprecated (declared at %s:%d)", + DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); + else + warning ("type is deprecated"); + } +} + /* Save the current INPUT_LOCATION on the top entry in the INPUT_FILE_STACK. Push a new entry for FILE and LINE, and set the INPUT_LOCATION accordingly. */ @@ -1706,7 +1769,7 @@ push_srcloc (const char *file, int line) { struct file_stack *fs; - fs = (struct file_stack *) xmalloc (sizeof (struct file_stack)); + fs = xmalloc (sizeof (struct file_stack)); fs->location = input_location; fs->next = input_file_stack; input_filename = file; @@ -1861,8 +1924,15 @@ rest_of_decl_compilation (tree decl, 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)) + is seen. But at end of compilation, do output code for them. + + We do output all variables when unit-at-a-time is active and rely on + callgraph code to defer them except for forward declarations + (see gcc.c-torture/compile/920624-1.c) */ + if ((at_end + || !DECL_DEFER_OUTPUT (decl) + || (flag_unit_at_a_time && DECL_INITIAL (decl))) + && !DECL_EXTERNAL (decl)) { if (flag_unit_at_a_time && !cgraph_global_info_ready && TREE_CODE (decl) != FUNCTION_DECL && top_level) @@ -2039,6 +2109,23 @@ rest_of_handle_delay_slots (tree decl, rtx insns) static void rest_of_handle_stack_regs (tree decl, rtx insns) { +#if defined (HAVE_ATTR_length) + /* If flow2 creates new instructions which need splitting + and scheduling after reload is not done, they might not be + split until final which doesn't allow splitting + if HAVE_ATTR_length. */ +#ifdef INSN_SCHEDULING + if (optimize && !flag_schedule_insns_after_reload) +#else + if (optimize) +#endif + { + timevar_push (TV_SHORTEN_BRANCH); + split_all_insns (1); + timevar_pop (TV_SHORTEN_BRANCH); + } +#endif + timevar_push (TV_REG_STACK); open_dump_file (DFI_stack, decl); @@ -2080,7 +2167,7 @@ rest_of_handle_machine_reorg (tree decl, rtx insns) /* Run new register allocator. Return TRUE if we must exit rest_of_compilation upon return. */ static bool -rest_of_handle_new_regalloc (tree decl, rtx insns, int *rebuild_notes) +rest_of_handle_new_regalloc (tree decl, rtx insns) { int failure; @@ -2119,7 +2206,6 @@ rest_of_handle_new_regalloc (tree decl, rtx insns, int *rebuild_notes) return true; reload_completed = 1; - *rebuild_notes = 0; return false; } @@ -2127,23 +2213,37 @@ rest_of_handle_new_regalloc (tree decl, rtx insns, int *rebuild_notes) /* Run old register allocator. Return TRUE if we must exit rest_of_compilation upon return. */ static bool -rest_of_handle_old_regalloc (tree decl, rtx insns, int *rebuild_notes) +rest_of_handle_old_regalloc (tree decl, rtx insns) { int failure; + int rebuild_notes; /* Allocate the reg_renumber array. */ allocate_reg_info (max_regno, FALSE, TRUE); /* And the reg_equiv_memory_loc array. */ - reg_equiv_memory_loc = (rtx *) xcalloc (max_regno, sizeof (rtx)); + reg_equiv_memory_loc = xcalloc (max_regno, sizeof (rtx)); allocate_initial_values (reg_equiv_memory_loc); regclass (insns, max_reg_num (), rtl_dump_file); - *rebuild_notes = local_alloc (); + rebuild_notes = local_alloc (); timevar_pop (TV_LOCAL_ALLOC); + /* Local allocation may have turned an indirect jump into a direct + jump. If so, we must rebuild the JUMP_LABEL fields of jumping + instructions. */ + if (rebuild_notes) + { + timevar_push (TV_JUMP); + + rebuild_jump_labels (insns); + purge_all_dead_edges (0); + + timevar_pop (TV_JUMP); + } + if (dump_file[DFI_lreg].enabled) { timevar_push (TV_DUMP); @@ -2206,13 +2306,14 @@ rest_of_handle_regrename (tree decl, rtx insns) static void rest_of_handle_reorder_blocks (tree decl, rtx insns) { - timevar_push (TV_REORDER_BLOCKS); + bool changed; open_dump_file (DFI_bbro, decl); /* Last attempt to optimize CFG, as scheduling, peepholing and insn splitting possibly introduced more crossjumping opportunities. */ - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE - | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)); + changed = cleanup_cfg (CLEANUP_EXPENSIVE + | (!HAVE_conditional_execution + ? CLEANUP_UPDATE_LIFE : 0)); if (flag_sched2_use_traces && flag_schedule_insns_after_reload) tracer (); @@ -2220,10 +2321,17 @@ rest_of_handle_reorder_blocks (tree decl, rtx insns) reorder_basic_blocks (); if (flag_reorder_blocks || (flag_sched2_use_traces && flag_schedule_insns_after_reload)) - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE); - + changed |= cleanup_cfg (CLEANUP_EXPENSIVE + | (!HAVE_conditional_execution + ? CLEANUP_UPDATE_LIFE : 0)); + + /* On conditional execution targets we can not update the life cheaply, so + we deffer the updating to after both cleanups. This may lose some cases + but should not be terribly bad. */ + if (changed && HAVE_conditional_execution) + update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, + PROP_DEATH_NOTES | PROP_REG_INFO); close_dump_file (DFI_bbro, print_rtl_with_bb, insns); - timevar_pop (TV_REORDER_BLOCKS); } #ifdef INSN_SCHEDULING @@ -2302,7 +2410,6 @@ rest_of_handle_regmove (tree decl, rtx insns) static void rest_of_handle_tracer (tree decl, rtx insns) { - timevar_push (TV_TRACER); open_dump_file (DFI_tracer, decl); if (rtl_dump_file) dump_flow_info (rtl_dump_file); @@ -2310,7 +2417,6 @@ rest_of_handle_tracer (tree decl, rtx insns) cleanup_cfg (CLEANUP_EXPENSIVE); reg_scan (insns, max_reg_num (), 0); close_dump_file (DFI_tracer, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_TRACER); } /* If-conversion and CFG cleanup. */ @@ -2351,6 +2457,20 @@ rest_of_handle_if_after_combine (tree decl, rtx insns) timevar_pop (TV_IFCVT); } +static void +rest_of_handle_web (tree decl, rtx insns) +{ + open_dump_file (DFI_web, decl); + timevar_push (TV_WEB); + web_main (); + delete_trivially_dead_insns (insns, max_reg_num ()); + cleanup_cfg (CLEANUP_EXPENSIVE); + + timevar_pop (TV_WEB); + close_dump_file (DFI_web, print_rtl_with_bb, insns); + reg_scan (get_insns (), max_reg_num (), 0); +} + /* Do branch profiling and static profile estimation passes. */ static void rest_of_handle_branch_prob (tree decl, rtx insns) @@ -2359,6 +2479,7 @@ rest_of_handle_branch_prob (tree decl, rtx insns) timevar_push (TV_BRANCH_PROB); open_dump_file (DFI_bp, decl); + if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities) branch_prob (); @@ -2374,10 +2495,25 @@ rest_of_handle_branch_prob (tree decl, rtx insns) estimate_probability (&loops); flow_loops_free (&loops); + free_dominance_info (CDI_DOMINATORS); close_dump_file (DFI_bp, print_rtl_with_bb, insns); timevar_pop (TV_BRANCH_PROB); } +/* Do optimizations based on expression value profiles. */ +static void +rest_of_handle_value_profile_transformations (tree decl, rtx insns) +{ + open_dump_file (DFI_vpt, decl); + timevar_push (TV_VPT); + + if (value_profile_transformations ()) + cleanup_cfg (CLEANUP_EXPENSIVE); + + timevar_pop (TV_VPT); + close_dump_file (DFI_vpt, print_rtl_with_bb, insns); +} + /* Do control and data flow analysis; write some of the results to the dump file. */ static void @@ -2398,7 +2534,12 @@ rest_of_handle_cfg (tree decl, rtx insns) life_analysis rarely eliminates modification of external memory. */ if (optimize) - mark_constant_function (); + { + /* Alias analysis depends on this information and mark_constant_function + depends on alias analysis. */ + reg_scan (insns, max_reg_num (), 1); + mark_constant_function (); + } close_dump_file (DFI_cfg, print_rtl_with_bb, insns); } @@ -2453,6 +2594,7 @@ rest_of_handle_jump_bypass (tree decl, rtx insns) open_dump_file (DFI_bypass, decl); cleanup_cfg (CLEANUP_EXPENSIVE); + reg_scan (insns, max_reg_num (), 1); if (bypass_jumps (rtl_dump_file)) { @@ -2483,8 +2625,9 @@ rest_of_handle_inlining (tree decl) /* 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) + if (cfun->rtl_inline_init) return 0; + cfun->rtl_inline_init = 1; /* If this is nested inside an inlined external function, pretend it was only declared. Since we cannot inline such functions, @@ -2512,8 +2655,12 @@ rest_of_handle_inlining (tree decl) timevar_pop (TV_INTEGRATION); if (lose || ! optimize) { - if (warn_inline && DECL_INLINE (decl)) - warning_with_decl (decl, lose); + if (warn_inline && lose && DECL_INLINE (decl)) + { + char *msg = concat ("%J", lose, NULL); + warning (msg, decl); + free (msg); + } DECL_ABSTRACT_ORIGIN (decl) = 0; /* Don't really compile an extern inline function. If we can't make it inline, pretend @@ -2524,16 +2671,8 @@ rest_of_handle_inlining (tree decl) return true; } } - else { - /* ??? Note that we used to just make it look like if - the "inline" keyword was specified when we decide - to inline it (because of -finline-functions). - garloff@suse.de, 2002-04-24: Add another flag to - actually record this piece of information. */ - if (!DECL_INLINE (decl)) - DID_INLINE_FUNC (decl) = 1; + else inlinable = DECL_INLINE (decl) = 1; - } } insns = get_insns (); @@ -2542,7 +2681,7 @@ rest_of_handle_inlining (tree decl) if (open_dump_file (DFI_rtl, decl)) { - if (DECL_SAVED_INSNS (decl)) + if (DECL_SAVED_INSNS (decl) && DECL_SAVED_INSNS (decl)->saved_for_inline) fprintf (rtl_dump_file, ";; (integrable)\n\n"); close_dump_file (DFI_rtl, print_rtl, insns); } @@ -2561,7 +2700,13 @@ rest_of_handle_inlining (tree decl) if (inlinable || (DECL_INLINE (decl) - && flag_inline_functions + /* Egad. This RTL deferral test conflicts with Fortran assumptions + for unreferenced symbols. See g77.f-torture/execute/980520-1.f. + But removing this line from the check breaks all languages that + use the call graph to output symbols. This hard-coded check is + the least invasive work-around. */ + && (flag_inline_functions + || strcmp (lang_hooks.name, "GNU F77") == 0) && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl) && ! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) && ! flag_keep_inline_functions) @@ -2616,71 +2761,6 @@ rest_of_handle_inlining (tree decl) return (bool) DECL_EXTERNAL (decl); } -/* Rest of compilation helper to convert the rtl to SSA form. */ -static rtx -rest_of_handle_ssa (tree decl, rtx insns) -{ - timevar_push (TV_TO_SSA); - open_dump_file (DFI_ssa, decl); - - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); - convert_to_ssa (); - - close_dump_file (DFI_ssa, print_rtl_with_bb, insns); - timevar_pop (TV_TO_SSA); - - /* Perform sparse conditional constant propagation, if requested. */ - if (flag_ssa_ccp) - { - timevar_push (TV_SSA_CCP); - open_dump_file (DFI_ssa_ccp, decl); - - ssa_const_prop (); - - close_dump_file (DFI_ssa_ccp, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_SSA_CCP); - } - - /* It would be useful to cleanup the CFG at this point, but block - merging and possibly other transformations might leave a PHI - node in the middle of a basic block, which is a strict no-no. */ - - /* The SSA implementation uses basic block numbers in its phi - nodes. Thus, changing the control-flow graph or the basic - blocks, e.g., calling find_basic_blocks () or cleanup_cfg (), - may cause problems. */ - - if (flag_ssa_dce) - { - /* Remove dead code. */ - - timevar_push (TV_SSA_DCE); - open_dump_file (DFI_ssa_dce, decl); - - insns = get_insns (); - ssa_eliminate_dead_code (); - - close_dump_file (DFI_ssa_dce, print_rtl_with_bb, insns); - timevar_pop (TV_SSA_DCE); - } - - /* Convert from SSA form. */ - - timevar_push (TV_FROM_SSA); - open_dump_file (DFI_ussa, decl); - - convert_from_ssa (); - /* New registers have been created. Rescan their usage. */ - reg_scan (insns, max_reg_num (), 1); - - close_dump_file (DFI_ussa, print_rtl_with_bb, insns); - timevar_pop (TV_FROM_SSA); - - ggc_collect (); - - return insns; -} - /* Try to identify useless null pointer tests and delete them. */ static void rest_of_handle_null_pointer (tree decl, rtx insns) @@ -2738,6 +2818,7 @@ rest_of_handle_life (tree decl, rtx insns) life_analysis (insns, rtl_dump_file, PROP_FINAL); if (optimize) cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_UPDATE_LIFE + | CLEANUP_LOG_LINKS | (flag_thread_jumps ? CLEANUP_THREADING : 0)); timevar_pop (TV_FLOW); @@ -2786,7 +2867,8 @@ rest_of_handle_cse (tree decl, rtx insns) tem = cse_main (insns, max_reg_num (), 0, rtl_dump_file); if (tem) rebuild_jump_labels (insns); - purge_all_dead_edges (0); + if (purge_all_dead_edges (0)) + delete_unreachable_blocks (); delete_trivially_dead_insns (insns, max_reg_num ()); @@ -2826,6 +2908,13 @@ rest_of_handle_cse2 (tree decl, rtx insns) dump_flow_info (rtl_dump_file); /* CFG is no longer maintained up-to-date. */ tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file); + + /* Run a pass to eliminate duplicated assignments to condition code + registers. We have to run this after bypass_jumps, because it + makes it harder for that pass to determine whether a jump can be + bypassed safely. */ + cse_condition_code_reg (); + purge_all_dead_edges (0); delete_trivially_dead_insns (insns, max_reg_num ()); @@ -2924,7 +3013,7 @@ rest_of_handle_loop_optimize (tree decl, rtx insns) free_bb_for_insn (); if (flag_unroll_loops) - do_unroll = 0; /* Having two unrollers is useless. */ + do_unroll = LOOP_AUTO_UNROLL; /* Having two unrollers is useless. */ else do_unroll = flag_old_unroll_loops ? LOOP_UNROLL : LOOP_AUTO_UNROLL; do_prefetch = flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0; @@ -3008,13 +3097,12 @@ void rest_of_compilation (tree decl) { rtx insns; - int rebuild_label_notes_after_reload; timevar_push (TV_REST_OF_COMPILATION); /* Register rtl specific functions for cfg. */ rtl_register_cfg_hooks (); - + /* Now that we're out of the frontend, we shouldn't have any more CONCATs anywhere. */ generating_concat_p = 0; @@ -3052,7 +3140,7 @@ rest_of_compilation (tree decl) /* We are now committed to emitting code for this function. Do any preparation, such as emitting abstract debug info for the inline before it gets mangled by optimization. */ - if (DECL_INLINE (decl)) + if (cgraph_function_possibly_inlined_p (decl)) (*debug_hooks->outlining_inline_function) (decl); /* Remove any notes we don't need. That will make iterating @@ -3094,10 +3182,6 @@ rest_of_compilation (tree decl) delete_unreachable_blocks (); - /* We have to issue these warnings now already, because CFG cleanups - further down may destroy the required information. */ - check_function_return_warnings (); - /* Turn NOTE_INSN_PREDICTIONs into branch predictions. */ if (flag_guess_branch_prob) { @@ -3109,6 +3193,14 @@ rest_of_compilation (tree decl) if (flag_optimize_sibling_calls) rest_of_handle_sibling_calls (insns); + /* We have to issue these warnings now already, because CFG cleanups + further down may destroy the required information. However, this + must be done after the sibcall optimization pass because the barrier + emitted for noreturn calls that are candidate for the optimization + is folded into the CALL_PLACEHOLDER until after this pass, so the + CFG is inaccurate. */ + check_function_return_warnings (); + timevar_pop (TV_JUMP); insn_locators_initialize (); @@ -3190,12 +3282,6 @@ rest_of_compilation (tree decl) if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl)) goto exit_rest_of_compilation; - /* Long term, this should probably move before the jump optimizer too, - but I didn't want to disturb the rtl_dump_and_exit and related - stuff at this time. */ - if (optimize > 0 && flag_ssa) - insns = rest_of_handle_ssa (decl, insns); - timevar_push (TV_JUMP); if (optimize) @@ -3230,9 +3316,6 @@ rest_of_compilation (tree decl) if (flag_loop_optimize) rest_of_handle_loop_optimize (decl, insns); - - if (flag_gcse) - rest_of_handle_jump_bypass (decl, insns); } timevar_push (TV_FLOW); @@ -3241,7 +3324,18 @@ rest_of_compilation (tree decl) if (optimize > 0 || profile_arc_flag || flag_test_coverage || flag_branch_probabilities) - rest_of_handle_branch_prob (decl, insns); + { + rest_of_handle_branch_prob (decl, insns); + + if (flag_branch_probabilities + && flag_profile_values + && flag_value_profile_transformations) + rest_of_handle_value_profile_transformations (decl, insns); + + /* Remove the death notes created for vpt. */ + if (flag_profile_values) + count_or_remove_death_notes (NULL, 1); + } if (optimize > 0) rest_of_handle_if_conversion (decl, insns); @@ -3249,11 +3343,19 @@ rest_of_compilation (tree decl) if (flag_tracer) rest_of_handle_tracer (decl, insns); - if (optimize > 0 - && (flag_unswitch_loops + if (optimize > 0) + { + if (flag_unswitch_loops || flag_peel_loops - || flag_unroll_loops)) - rest_of_handle_loop2 (decl, insns); + || flag_unroll_loops) + rest_of_handle_loop2 (decl, insns); + + if (flag_gcse) + rest_of_handle_jump_bypass (decl, insns); + } + + if (flag_web) + rest_of_handle_web (decl, insns); if (flag_rerun_cse_after_loop) rest_of_handle_cse2 (decl, insns); @@ -3304,14 +3406,12 @@ rest_of_compilation (tree decl) if (flag_new_regalloc) { - if (rest_of_handle_new_regalloc (decl, insns, - &rebuild_label_notes_after_reload)) + if (rest_of_handle_new_regalloc (decl, insns)) goto exit_rest_of_compilation; } else { - if (rest_of_handle_old_regalloc (decl, insns, - &rebuild_label_notes_after_reload)) + if (rest_of_handle_old_regalloc (decl, insns)) goto exit_rest_of_compilation; } @@ -3324,22 +3424,13 @@ rest_of_compilation (tree decl) { timevar_push (TV_RELOAD_CSE_REGS); reload_cse_regs (insns); + /* reload_cse_regs can eliminate potentially-trapping MEMs. + Remove any EH edges associated with them. */ + if (flag_non_call_exceptions) + purge_all_dead_edges (0); timevar_pop (TV_RELOAD_CSE_REGS); } - /* Register allocation and reloading may have turned an indirect jump into - a direct jump. If so, we must rebuild the JUMP_LABEL fields of - jumping instructions. */ - if (rebuild_label_notes_after_reload) - { - timevar_push (TV_JUMP); - - rebuild_jump_labels (insns); - purge_all_dead_edges (0); - - timevar_pop (TV_JUMP); - } - close_dump_file (DFI_postreload, print_rtl_with_bb, insns); /* Re-create the death notes which were deleted during reload. */ @@ -3379,7 +3470,7 @@ rest_of_compilation (tree decl) if (optimize) { - life_analysis (insns, rtl_dump_file, PROP_FINAL); + life_analysis (insns, rtl_dump_file, PROP_POSTRELOAD); cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)); @@ -3413,42 +3504,48 @@ rest_of_compilation (tree decl) } #endif - if (optimize > 0) - { - if (flag_rename_registers || flag_cprop_registers) - rest_of_handle_regrename (decl, insns); - - rest_of_handle_reorder_blocks (decl, insns); - } - + open_dump_file (DFI_ce3, decl); + if (optimize) + /* Last attempt to optimize CFG, as scheduling, peepholing and insn + splitting possibly introduced more crossjumping opportunities. */ + cleanup_cfg (CLEANUP_EXPENSIVE + | CLEANUP_UPDATE_LIFE + | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)); if (flag_if_conversion2) { timevar_push (TV_IFCVT2); - open_dump_file (DFI_ce3, decl); if_convert (1); - close_dump_file (DFI_ce3, print_rtl_with_bb, insns); timevar_pop (TV_IFCVT2); } + close_dump_file (DFI_ce3, print_rtl_with_bb, insns); - if (flag_branch_target_load_optimize2) - { - /* Leave this a warning for now so that it is possible to experiment - with running this pass twice. In 3.6, we should either make this - an error, or use separate dump files. */ - if (flag_branch_target_load_optimize) - warning ("branch target register load optimization is not intended " - "to be run twice"); + if (optimize > 0) + { + if (flag_rename_registers || flag_cprop_registers) + rest_of_handle_regrename (decl, insns); - open_dump_file (DFI_branch_target_load, decl); + rest_of_handle_reorder_blocks (decl, insns); + } - branch_target_load_optimize (insns, true); + if (flag_branch_target_load_optimize2) + { + /* Leave this a warning for now so that it is possible to experiment + with running this pass twice. In 3.6, we should either make this + an error, or use separate dump files. */ + if (flag_branch_target_load_optimize) + warning ("branch target register load optimization is not intended " + "to be run twice"); - close_dump_file (DFI_branch_target_load, print_rtl_with_bb, insns); + open_dump_file (DFI_branch_target_load, decl); - ggc_collect (); - } + branch_target_load_optimize (insns, true); + + close_dump_file (DFI_branch_target_load, print_rtl_with_bb, insns); + + ggc_collect (); + } #ifdef INSN_SCHEDULING if (optimize > 0 && flag_schedule_insns_after_reload) @@ -3573,9 +3670,6 @@ rest_of_compilation (tree decl) if (! DECL_DEFER_OUTPUT (decl)) { free_after_compilation (cfun); - - /* Clear integrate.c's pointer to the cfun structure we just - destroyed. */ DECL_SAVED_INSNS (decl) = 0; } cfun = 0; @@ -3585,24 +3679,8 @@ rest_of_compilation (tree decl) timevar_pop (TV_REST_OF_COMPILATION); } -/* Display help for generic options. */ -void -display_help (void) -{ - unsigned long i; - - for (i = ARRAY_SIZE (debug_args); i--;) - { - if (debug_args[i].description != NULL) - printf (" -g%-21s %s\n", - debug_args[i].arg, _(debug_args[i].description)); - } - - display_target_options (); -} - /* Display help for target options. */ -void +void display_target_options (void) { int undoc, i; @@ -3734,124 +3812,6 @@ const char *const debug_type_names[] = "none", "stabs", "coff", "dwarf-1", "dwarf-2", "xcoff", "vms" }; -/* Parse a -g... command line switch. ARG is the value after the -g. - It is safe to access 'ARG - 2' to generate the full switch name. - Return the number of strings consumed. */ - -void -decode_g_option (const char *arg) -{ - static unsigned level = 0; - /* A lot of code assumes write_symbols == NO_DEBUG if the - debugging level is 0 (thus -gstabs1 -gstabs0 would lose track - of what debugging type has been selected). This records the - selected type. It is an error to specify more than one - debugging type. */ - static enum debug_info_type selected_debug_type = NO_DEBUG; - /* Nonzero if debugging format has been explicitly set. - -g and -ggdb don't explicitly set the debugging format so - -gdwarf -g3 is equivalent to -gdwarf3. */ - static int type_explicitly_set_p = 0; - - /* The maximum admissible debug level value. */ - static const unsigned max_debug_level = 3; - - /* Look up ARG in the table. */ - for (da = debug_args; da->arg; da++) - { - const int da_len = strlen (da->arg); - - if (da_len == 0 || ! strncmp (arg, da->arg, da_len)) - { - enum debug_info_type type = da->debug_type; - const char *p = arg + da_len; - - if (*p && ! ISDIGIT (*p)) - continue; - - /* A debug flag without a level defaults to level 2. - Note we do not want to call read_integral_parameter - for that case since it will call atoi which - will return zero. - - ??? We may want to generalize the interface to - read_integral_parameter to better handle this case - if this case shows up often. */ - if (*p) - level = read_integral_parameter (p, 0, max_debug_level + 1); - else - level = (level == 0) ? 2 : level; - - if (da_len > 1 && *p && !strncmp (arg, "dwarf", da_len)) - { - error ("use -gdwarf -g%d for DWARF v1, level %d", - level, level); - if (level == 2) - error ("use -gdwarf-2 for DWARF v2"); - } - - if (level > max_debug_level) - { - warning ("\ -ignoring option `%s' due to invalid debug level specification", - arg - 2); - level = debug_info_level; - } - - if (type == NO_DEBUG) - { - type = PREFERRED_DEBUGGING_TYPE; - - if (da_len > 1 && strncmp (arg, "gdb", da_len) == 0) - { -#ifdef DWARF2_DEBUGGING_INFO - type = DWARF2_DEBUG; -#else -#ifdef DBX_DEBUGGING_INFO - type = DBX_DEBUG; -#endif -#endif - } - } - - if (type == NO_DEBUG) - warning ("`%s': unknown or unsupported -g option", arg - 2); - - /* Does it conflict with an already selected type? */ - if (type_explicitly_set_p - /* -g/-ggdb don't conflict with anything. */ - && da->debug_type != NO_DEBUG - && type != selected_debug_type) - warning ("`%s' ignored, conflicts with `-g%s'", - arg - 2, debug_type_names[(int) selected_debug_type]); - else - { - /* If the format has already been set, -g/-ggdb - only change the debug level. */ - if (type_explicitly_set_p && da->debug_type == NO_DEBUG) - /* Don't change debugging type. */ - ; - else - { - selected_debug_type = type; - type_explicitly_set_p = da->debug_type != NO_DEBUG; - } - - write_symbols = (level == 0 - ? NO_DEBUG - : selected_debug_type); - use_gnu_debug_info_extensions = da->use_extensions_p; - debug_info_level = (enum debug_info_level) level; - } - - break; - } - } - - if (! da->arg) - warning ("`-g%s': unknown or unsupported -g option", arg); -} - /* Decode -m switches. */ /* Decode the switch -mNAME. */ @@ -4053,7 +4013,7 @@ init_asm_output (const char *name) if (asm_file_name == 0) { int len = strlen (dump_base_name); - char *dumpname = (char *) xmalloc (len + 6); + char *dumpname = xmalloc (len + 6); memcpy (dumpname, dump_base_name, len + 1); strip_off_ending (dumpname, len); strcat (dumpname, ".s"); @@ -4068,7 +4028,7 @@ init_asm_output (const char *name) } #ifdef IO_BUFFER_SIZE - setvbuf (asm_out_file, (char *) xmalloc (IO_BUFFER_SIZE), + setvbuf (asm_out_file, xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE); #endif @@ -4091,6 +4051,146 @@ init_asm_output (const char *name) } } +/* Default version of get_pch_validity. + By default, every flag difference is fatal; that will be mostly right for + most targets, but completely right for very few. */ + +void * +default_get_pch_validity (size_t *len) +{ +#ifdef TARGET_OPTIONS + size_t i; +#endif + char *result, *r; + + *len = sizeof (target_flags) + 2; +#ifdef TARGET_OPTIONS + for (i = 0; i < ARRAY_SIZE (target_options); i++) + { + *len += 1; + if (*target_options[i].variable) + *len += strlen (*target_options[i].variable); + } +#endif + + result = r = xmalloc (*len); + r[0] = flag_pic; + r[1] = flag_pie; + r += 2; + memcpy (r, &target_flags, sizeof (target_flags)); + r += sizeof (target_flags); + +#ifdef TARGET_OPTIONS + for (i = 0; i < ARRAY_SIZE (target_options); i++) + { + const char *str = *target_options[i].variable; + size_t l; + if (! str) + str = ""; + l = strlen (str) + 1; + memcpy (r, str, l); + r += l; + } +#endif + + return result; +} + +/* Default version of pch_valid_p. */ + +const char * +default_pch_valid_p (const void *data_p, size_t len) +{ + const char *data = (const char *)data_p; + const char *flag_that_differs = NULL; + size_t i; + + /* -fpic and -fpie also usually make a PCH invalid. */ + if (data[0] != flag_pic) + return _("created and used with different settings of -fpic"); + if (data[1] != flag_pie) + return _("created and used with different settings of -fpie"); + data += 2; + + /* Check target_flags. */ + if (memcmp (data, &target_flags, sizeof (target_flags)) != 0) + { + for (i = 0; i < ARRAY_SIZE (target_switches); i++) + { + int bits; + int tf; + + memcpy (&tf, data, sizeof (target_flags)); + + bits = target_switches[i].value; + if (bits < 0) + bits = -bits; + if ((target_flags & bits) != (tf & bits)) + { + flag_that_differs = target_switches[i].name; + goto make_message; + } + } + abort (); + } + data += sizeof (target_flags); + len -= sizeof (target_flags); + + /* Check string options. */ +#ifdef TARGET_OPTIONS + for (i = 0; i < ARRAY_SIZE (target_options); i++) + { + const char *str = *target_options[i].variable; + size_t l; + if (! str) + str = ""; + l = strlen (str) + 1; + if (len < l || memcmp (data, str, l) != 0) + { + flag_that_differs = target_options[i].prefix; + goto make_message; + } + data += l; + len -= l; + } +#endif + + return NULL; + + make_message: + { + char *r; + asprintf (&r, _("created and used with differing settings of `-m%s'"), + flag_that_differs); + if (r == NULL) + return _("out of memory"); + return r; + } +} + +/* Default tree printer. Handles declarations only. */ +static bool +default_tree_printer (pretty_printer * pp, text_info *text) +{ + switch (*text->format_spec) + { + case 'D': + case 'F': + case 'T': + { + tree t = va_arg (*text->args_ptr, tree); + const char *n = DECL_NAME (t) + ? (*lang_hooks.decl_printable_name) (t, 2) + : ""; + pp_string (pp, n); + } + return true; + + default: + return false; + } +} + /* Initialization of the front end environment, before command line options are parsed. Signal handlers, internationalization etc. ARGV0 is main's argv[0]. */ @@ -4110,6 +4210,13 @@ general_init (const char *argv0) gcc_init_libintl (); + /* Initialize the diagnostics reporting machinery, so option parsing + can give warnings and errors. */ + diagnostic_initialize (global_dc); + /* Set a default printer. Language specific initializations will + override it later. */ + pp_format_decoder (global_dc->printer) = &default_tree_printer; + /* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages. */ #ifdef SIGSEGV signal (SIGSEGV, crash_signal); @@ -4133,14 +4240,11 @@ general_init (const char *argv0) /* Other host-specific signal setup. */ (*host_hooks.extra_signals)(); - /* Initialize the diagnostics reporting machinery, so option parsing - can give warnings and errors. */ - diagnostic_initialize (global_dc); - /* Initialize the garbage-collector, string pools and tree type hash table. */ init_ggc (); init_stringpool (); + linemap_init (&line_table); init_ttree (); /* Initialize register usage now so switches may override. */ @@ -4235,6 +4339,9 @@ process_options (void) if (flag_unit_at_a_time && ! lang_hooks.callgraph.expand_function) flag_unit_at_a_time = 0; + if (flag_value_profile_transformations) + flag_profile_values = 1; + /* Warn about options that are not supported on this machine. */ #ifndef INSN_SCHEDULING if (flag_schedule_insns || flag_schedule_insns_after_reload) @@ -4275,32 +4382,38 @@ process_options (void) profile_flag = 0; } + /* A lot of code assumes write_symbols == NO_DEBUG if the debugging + level is 0. */ + if (debug_info_level == DINFO_LEVEL_NONE) + write_symbols = NO_DEBUG; + /* Now we know write_symbols, set up the debug hooks based on it. By default we do nothing for debug output. */ + if (write_symbols == NO_DEBUG) + debug_hooks = &do_nothing_debug_hooks; #if defined(DBX_DEBUGGING_INFO) - if (write_symbols == DBX_DEBUG) + else if (write_symbols == DBX_DEBUG) debug_hooks = &dbx_debug_hooks; #endif #if defined(XCOFF_DEBUGGING_INFO) - if (write_symbols == XCOFF_DEBUG) + else if (write_symbols == XCOFF_DEBUG) debug_hooks = &xcoff_debug_hooks; #endif #ifdef SDB_DEBUGGING_INFO - if (write_symbols == SDB_DEBUG) + else if (write_symbols == SDB_DEBUG) debug_hooks = &sdb_debug_hooks; #endif -#ifdef DWARF_DEBUGGING_INFO - if (write_symbols == DWARF_DEBUG) - debug_hooks = &dwarf_debug_hooks; -#endif #ifdef DWARF2_DEBUGGING_INFO - if (write_symbols == DWARF2_DEBUG) + else if (write_symbols == DWARF2_DEBUG) debug_hooks = &dwarf2_debug_hooks; #endif #ifdef VMS_DEBUGGING_INFO - if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG) + else if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG) debug_hooks = &vmsdbg_debug_hooks; #endif + else + error ("target system does not support the \"%s\" debug format", + debug_type_names[write_symbols]); /* If auxiliary info generation is desired, open the output file. This goes in the same directory as the source file--unlike @@ -4368,9 +4481,8 @@ process_options (void) static void backend_init (void) { - /* init_emit_once uses reg_raw_mode and therefore must be called - after init_regs which initialized reg_raw_mode. */ - init_regs (); + init_adjust_machine_modes (); + init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL || debug_info_level == DINFO_LEVEL_VERBOSE #ifdef VMS_DEBUGGING_INFO @@ -4379,6 +4491,8 @@ backend_init (void) #endif || flag_test_coverage || warn_notreached); + + init_regs (); init_fake_stack_mems (); init_alias_once (); init_loop (); @@ -4485,6 +4599,8 @@ finalize (void) ggc_print_statistics (); stringpool_statistics (); dump_tree_statistics (); + dump_rtx_statistics (); + dump_varray_statistics (); } /* Free up memory for the benefit of leak detectors. */ @@ -4542,7 +4658,6 @@ do_compile (void) } /* 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.