toplev.c revision 98573
118334Speter/* Top level of GNU C compiler
272566Sobrien   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
390282Sobrien   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
418334Speter
590282SobrienThis file is part of GCC.
618334Speter
790282SobrienGCC is free software; you can redistribute it and/or modify it under
890282Sobrienthe terms of the GNU General Public License as published by the Free
990282SobrienSoftware Foundation; either version 2, or (at your option) any later
1090282Sobrienversion.
1118334Speter
1290282SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1390282SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1490282SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1590282Sobrienfor more details.
1618334Speter
1718334SpeterYou should have received a copy of the GNU General Public License
1890282Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
1990282SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
2090282Sobrien02111-1307, USA.  */
2118334Speter
2252558Sobrien/* $FreeBSD: head/contrib/gcc/toplev.c 98573 2002-06-21 18:21:30Z obrien $ */
2352558Sobrien
2418334Speter/* This is the top level of cc1/c++.
2518334Speter   It parses command args, opens files, invokes the various passes
2618334Speter   in the proper order, and counts the time used by each.
2718334Speter   Error messages and low-level interface to malloc also handled here.  */
2818334Speter
2918334Speter#include "config.h"
3050615Sobrien#undef FLOAT /* This is for hpux. They should change hpux.  */
3150615Sobrien#undef FFS  /* Some systems define this in param.h.  */
3250615Sobrien#include "system.h"
3318334Speter#include <signal.h>
3418334Speter#include <setjmp.h>
3518334Speter
3650615Sobrien#ifdef HAVE_SYS_RESOURCE_H
3750615Sobrien# include <sys/resource.h>
3818334Speter#endif
3950615Sobrien
4050615Sobrien#ifdef HAVE_SYS_TIMES_H
4150615Sobrien# include <sys/times.h>
4218334Speter#endif
4318334Speter
4418334Speter#include "input.h"
4518334Speter#include "tree.h"
4618334Speter#include "rtl.h"
4790282Sobrien#include "tm_p.h"
4818334Speter#include "flags.h"
4918334Speter#include "insn-attr.h"
5050615Sobrien#include "insn-config.h"
5190282Sobrien#include "insn-flags.h"
5290282Sobrien#include "hard-reg-set.h"
5350615Sobrien#include "recog.h"
5418334Speter#include "output.h"
5550615Sobrien#include "except.h"
5690282Sobrien#include "function.h"
5750615Sobrien#include "toplev.h"
5852558Sobrien#include "expr.h"
5952558Sobrien#include "basic-block.h"
6052558Sobrien#include "intl.h"
6190282Sobrien#include "ggc.h"
6290282Sobrien#include "graph.h"
6390282Sobrien#include "loop.h"
6490282Sobrien#include "regs.h"
6590282Sobrien#include "timevar.h"
6690282Sobrien#include "diagnostic.h"
6790282Sobrien#include "ssa.h"
6890282Sobrien#include "params.h"
6990282Sobrien#include "reload.h"
7090282Sobrien#include "dwarf2asm.h"
7190282Sobrien#include "integrate.h"
7290282Sobrien#include "debug.h"
7390282Sobrien#include "target.h"
7490282Sobrien#include "langhooks.h"
7518334Speter
7650615Sobrien#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
7750615Sobrien#include "dwarf2out.h"
7850615Sobrien#endif
7950615Sobrien
8050615Sobrien#if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
8150615Sobrien#include "dbxout.h"
8250615Sobrien#endif
8350615Sobrien
8450615Sobrien#ifdef SDB_DEBUGGING_INFO
8550615Sobrien#include "sdbout.h"
8650615Sobrien#endif
8750615Sobrien
8818334Speter#ifdef XCOFF_DEBUGGING_INFO
8990282Sobrien#include "xcoffout.h"		/* Needed for external data
9090282Sobrien				   declarations for e.g. AIX 4.x.  */
9118334Speter#endif
9290282Sobrien
9390282Sobrien#ifdef HALF_PIC_DEBUG
9490282Sobrien#include "halfpic.h"
9590282Sobrien#endif
9618334Speter
9718334Speter/* Carry information from ASM_DECLARE_OBJECT_NAME
9818334Speter   to ASM_FINISH_DECLARE_OBJECT.  */
9918334Speter
10018334Speterextern int size_directive_output;
10118334Speterextern tree last_assemble_variable_decl;
10218334Speter
10390282Sobrienstatic void general_init PARAMS ((char *));
10490282Sobrienstatic void parse_options_and_default_flags PARAMS ((int, char **));
10590282Sobrienstatic void do_compile PARAMS ((void));
10690282Sobrienstatic void process_options PARAMS ((void));
10790282Sobrienstatic void lang_independent_init PARAMS ((void));
10890282Sobrienstatic int lang_dependent_init PARAMS ((const char *));
10990282Sobrienstatic void init_asm_output PARAMS ((const char *));
11090282Sobrienstatic void finalize PARAMS ((void));
11118334Speter
11290282Sobrienstatic void set_target_switch PARAMS ((const char *));
11390282Sobrienstatic const char *decl_name PARAMS ((tree, int));
11450615Sobrien
11590282Sobrienstatic void float_signal PARAMS ((int)) ATTRIBUTE_NORETURN;
11690282Sobrienstatic void crash_signal PARAMS ((int)) ATTRIBUTE_NORETURN;
11790282Sobrienstatic void set_float_handler PARAMS ((jmp_buf));
11890282Sobrienstatic void compile_file PARAMS ((void));
11990282Sobrienstatic void display_help PARAMS ((void));
12090282Sobrienstatic void display_target_options PARAMS ((void));
12118334Speter
12290282Sobrienstatic void decode_d_option PARAMS ((const char *));
12390282Sobrienstatic int decode_f_option PARAMS ((const char *));
12490282Sobrienstatic int decode_W_option PARAMS ((const char *));
12590282Sobrienstatic int decode_g_option PARAMS ((const char *));
12690282Sobrienstatic unsigned int independent_decode_option PARAMS ((int, char **));
12790282Sobrien
12890282Sobrienstatic void print_version PARAMS ((FILE *, const char *));
12990282Sobrienstatic int print_single_switch PARAMS ((FILE *, int, int, const char *,
13052558Sobrien				      const char *, const char *,
13152558Sobrien				      const char *, const char *));
13290282Sobrienstatic void print_switch_values PARAMS ((FILE *, int, int, const char *,
13352558Sobrien				       const char *, const char *));
13452558Sobrien
13550615Sobrien/* Length of line when printing switch values.  */
13650615Sobrien#define MAX_LINE 75
13718334Speter
13818334Speter/* Name of program invoked, sans directories.  */
13918334Speter
14090282Sobrienconst char *progname;
14118334Speter
14290282Sobrien/* Copy of arguments to toplev_main.  */
14318334Speterint save_argc;
14418334Speterchar **save_argv;
14518334Speter
14618334Speter/* Name of current original source file (what was input to cpp).
14718334Speter   This comes from each #-command in the actual input.  */
14818334Speter
14990282Sobrienconst char *input_filename;
15018334Speter
15118334Speter/* Name of top-level original source file (what was input to cpp).
15218334Speter   This comes from the #-command at the beginning of the actual input.
15318334Speter   If there isn't any there, then this is the cc1 input file name.  */
15418334Speter
15590282Sobrienconst char *main_input_filename;
15618334Speter
15718334Speter/* Current line number in real source file.  */
15818334Speter
15918334Speterint lineno;
16018334Speter
16152558Sobrien/* Nonzero if it is unsafe to create any new pseudo registers.  */
16252558Sobrienint no_new_pseudos;
16352558Sobrien
16418334Speter/* Stack of currently pending input files.  */
16518334Speter
16618334Speterstruct file_stack *input_file_stack;
16718334Speter
16818334Speter/* Incremented on each change to input_file_stack.  */
16918334Speterint input_file_stack_tick;
17018334Speter
17118334Speter/* Name to use as base of names for dump output files.  */
17218334Speter
17352558Sobrienconst char *dump_base_name;
17418334Speter
17590282Sobrien/* Format to use to print dumpfile index value */
17690282Sobrien#ifndef DUMPFILE_FORMAT
17790282Sobrien#define DUMPFILE_FORMAT ".%02d."
17890282Sobrien#endif
17990282Sobrien
18018334Speter/* Bit flags that specify the machine subtype we are compiling for.
18118334Speter   Bits are tested using macros TARGET_... defined in the tm.h file
18218334Speter   and set by `-m...' switches.  Must be defined in rtlanal.c.  */
18318334Speter
18418334Speterextern int target_flags;
18518334Speter
18690282Sobrien/* Debug hooks - dependent upon command line options.  */
18718334Speter
18890282Sobrienstruct gcc_debug_hooks *debug_hooks = &do_nothing_debug_hooks;
18990282Sobrien
19090282Sobrien/* Describes a dump file.  */
19190282Sobrien
19290282Sobrienstruct dump_file_info
19390282Sobrien{
19490282Sobrien  /* The unique extension to apply, e.g. ".jump".  */
19590282Sobrien  const char *const extension;
19690282Sobrien
19790282Sobrien  /* The -d<c> character that enables this dump file.  */
19890282Sobrien  char const debug_switch;
19990282Sobrien
20090282Sobrien  /* True if there is a corresponding graph dump file.  */
20190282Sobrien  char const graph_dump_p;
20290282Sobrien
20390282Sobrien  /* True if the user selected this dump.  */
20490282Sobrien  char enabled;
20590282Sobrien
20690282Sobrien  /* True if the files have been initialized (ie truncated).  */
20790282Sobrien  char initialized;
20890282Sobrien};
20990282Sobrien
21090282Sobrien/* Enumerate the extant dump files.  */
21190282Sobrien
21290282Sobrienenum dump_file_index
21390282Sobrien{
21490282Sobrien  DFI_rtl,
21590282Sobrien  DFI_sibling,
21690282Sobrien  DFI_eh,
21790282Sobrien  DFI_jump,
21890282Sobrien  DFI_ssa,
21990282Sobrien  DFI_ssa_ccp,
22090282Sobrien  DFI_ssa_dce,
22190282Sobrien  DFI_ussa,
22290282Sobrien  DFI_cse,
22390282Sobrien  DFI_addressof,
22490282Sobrien  DFI_gcse,
22590282Sobrien  DFI_loop,
22690282Sobrien  DFI_cse2,
22790282Sobrien  DFI_cfg,
22890282Sobrien  DFI_bp,
22990282Sobrien  DFI_life,
23090282Sobrien  DFI_combine,
23190282Sobrien  DFI_ce,
23290282Sobrien  DFI_regmove,
23390282Sobrien  DFI_sched,
23490282Sobrien  DFI_lreg,
23590282Sobrien  DFI_greg,
23690282Sobrien  DFI_postreload,
23790282Sobrien  DFI_flow2,
23890282Sobrien  DFI_peephole2,
23990282Sobrien  DFI_rnreg,
24090282Sobrien  DFI_ce2,
24190282Sobrien  DFI_sched2,
24290282Sobrien  DFI_stack,
24390282Sobrien  DFI_bbro,
24490282Sobrien  DFI_mach,
24590282Sobrien  DFI_dbr,
24690282Sobrien  DFI_MAX
24790282Sobrien};
24890282Sobrien
24990282Sobrien/* Describes all the dump files.  Should be kept in order of the
25090282Sobrien   pass and in sync with dump_file_index above.
25190282Sobrien
25290282Sobrien   Remaining -d letters:
25390282Sobrien
25490282Sobrien	"              o q   u     "
25590282Sobrien	"       H JK   OPQ  TUV  YZ"
25690282Sobrien*/
25790282Sobrien
25890282Sobrienstatic struct dump_file_info dump_file[DFI_MAX] =
25990282Sobrien{
26090282Sobrien  { "rtl",	'r', 0, 0, 0 },
26190282Sobrien  { "sibling",  'i', 0, 0, 0 },
26290282Sobrien  { "eh",	'h', 0, 0, 0 },
26390282Sobrien  { "jump",	'j', 0, 0, 0 },
26490282Sobrien  { "ssa",	'e', 1, 0, 0 },
26590282Sobrien  { "ssaccp",	'W', 1, 0, 0 },
26690282Sobrien  { "ssadce",	'X', 1, 0, 0 },
26790282Sobrien  { "ussa",	'e', 1, 0, 0 },	/* Yes, duplicate enable switch.  */
26890282Sobrien  { "cse",	's', 0, 0, 0 },
26990282Sobrien  { "addressof", 'F', 0, 0, 0 },
27090282Sobrien  { "gcse",	'G', 1, 0, 0 },
27190282Sobrien  { "loop",	'L', 1, 0, 0 },
27290282Sobrien  { "cse2",	't', 1, 0, 0 },
27390282Sobrien  { "cfg",	'f', 1, 0, 0 },
27490282Sobrien  { "bp",	'b', 1, 0, 0 },
27590282Sobrien  { "life",	'f', 1, 0, 0 },	/* Yes, duplicate enable switch.  */
27690282Sobrien  { "combine",	'c', 1, 0, 0 },
27790282Sobrien  { "ce",	'C', 1, 0, 0 },
27890282Sobrien  { "regmove",	'N', 1, 0, 0 },
27990282Sobrien  { "sched",	'S', 1, 0, 0 },
28090282Sobrien  { "lreg",	'l', 1, 0, 0 },
28190282Sobrien  { "greg",	'g', 1, 0, 0 },
28290282Sobrien  { "postreload", 'o', 1, 0, 0 },
28390282Sobrien  { "flow2",	'w', 1, 0, 0 },
28490282Sobrien  { "peephole2", 'z', 1, 0, 0 },
28590282Sobrien  { "rnreg",	'n', 1, 0, 0 },
28690282Sobrien  { "ce2",	'E', 1, 0, 0 },
28790282Sobrien  { "sched2",	'R', 1, 0, 0 },
28890282Sobrien  { "stack",	'k', 1, 0, 0 },
28990282Sobrien  { "bbro",	'B', 1, 0, 0 },
29090282Sobrien  { "mach",	'M', 1, 0, 0 },
29190282Sobrien  { "dbr",	'd', 0, 0, 0 },
29290282Sobrien};
29390282Sobrien
29490282Sobrienstatic int open_dump_file PARAMS ((enum dump_file_index, tree));
29590282Sobrienstatic void close_dump_file PARAMS ((enum dump_file_index,
29690282Sobrien				     void (*) (FILE *, rtx), rtx));
29790282Sobrien
29890282Sobrien/* Other flags saying which kinds of debugging dump have been requested.  */
29990282Sobrien
30090282Sobrienint rtl_dump_and_exit;
30190282Sobrienint flag_print_asm_name;
30290282Sobrienstatic int version_flag;
30390282Sobrienstatic char *filename;
30452558Sobrienenum graph_dump_types graph_dump_format;
30518334Speter
30618334Speter/* Name for output file of assembly code, specified with -o.  */
30718334Speter
30818334Speterchar *asm_file_name;
30918334Speter
31018334Speter/* Value of the -G xx switch, and whether it was passed or not.  */
31118334Speterint g_switch_value;
31218334Speterint g_switch_set;
31318334Speter
31418334Speter/* Type(s) of debugging information we are producing (if any).
31518334Speter   See flags.h for the definitions of the different possible
31618334Speter   types of debugging information.  */
31718334Speterenum debug_info_type write_symbols = NO_DEBUG;
31818334Speter
31918334Speter/* Level of debugging information we are producing.  See flags.h
32018334Speter   for the definitions of the different possible levels.  */
32118334Speterenum debug_info_level debug_info_level = DINFO_LEVEL_NONE;
32218334Speter
32318334Speter/* Nonzero means use GNU-only extensions in the generated symbolic
32418334Speter   debugging information.  */
32518334Speter/* Currently, this only has an effect when write_symbols is set to
32618334Speter   DBX_DEBUG, XCOFF_DEBUG, or DWARF_DEBUG.  */
32718334Speterint use_gnu_debug_info_extensions = 0;
32818334Speter
32918334Speter/* Nonzero means do optimizations.  -O.
33018334Speter   Particular numeric values stand for particular amounts of optimization;
33118334Speter   thus, -O2 stores 2 here.  However, the optimizations beyond the basic
33218334Speter   ones are not controlled directly by this variable.  Instead, they are
33318334Speter   controlled by individual `flag_...' variables that are defaulted
33418334Speter   based on this variable.  */
33518334Speter
33618334Speterint optimize = 0;
33718334Speter
33850615Sobrien/* Nonzero means optimize for size.  -Os.
33950615Sobrien   The only valid values are zero and non-zero. When optimize_size is
34050615Sobrien   non-zero, optimize defaults to 2, but certain individual code
34150615Sobrien   bloating optimizations are disabled.  */
34250615Sobrien
34350615Sobrienint optimize_size = 0;
34450615Sobrien
34590282Sobrien/* Nonzero if we should exit after parsing options.  */
34690282Sobrienstatic int exit_after_options = 0;
34718334Speter
34890282Sobrien/* The FUNCTION_DECL for the function currently being compiled,
34990282Sobrien   or 0 if between functions.  */
35090282Sobrientree current_function_decl;
35118334Speter
35290282Sobrien/* Set to the FUNC_BEGIN label of the current function, or NULL_TREE
35390282Sobrien   if none.  */
35490282Sobrientree current_function_func_begin_label;
35590282Sobrien
35650615Sobrien/* Pointer to function to compute the name to use to print a declaration.
35750615Sobrien   DECL is the declaration in question.
35850615Sobrien   VERBOSITY determines what information will be printed:
35950615Sobrien     0: DECL_NAME, demangled as necessary.
36050615Sobrien     1: and scope information.
36150615Sobrien     2: and any other information that might be interesting, such as function
36250615Sobrien        parameter types in C++.  */
36318334Speter
36490282Sobrienconst char *(*decl_printable_name)	PARAMS ((tree, int));
36518334Speter
36618334Speter/* Pointer to function to compute rtl for a language-specific tree code.  */
36718334Speter
36852558Sobrientypedef rtx (*lang_expand_expr_t)
36990282Sobrien  PARAMS ((union tree_node *, rtx, enum machine_mode,
37052558Sobrien	  enum expand_modifier modifier));
37118334Speter
37252558Sobrienlang_expand_expr_t lang_expand_expr = 0;
37352558Sobrien
37418334Speter/* Pointer to function to finish handling an incomplete decl at the
37518334Speter   end of compilation.  */
37618334Speter
37790282Sobrienvoid (*incomplete_decl_finalize_hook) PARAMS ((tree)) = 0;
37818334Speter
37990282Sobrien/* Nonzero if doing dwarf2 duplicate elimination.  */
38090282Sobrien
38190282Sobrienint flag_eliminate_dwarf2_dups = 0;
38290282Sobrien
38318334Speter/* Nonzero if generating code to do profiling.  */
38418334Speter
38518334Speterint profile_flag = 0;
38618334Speter
38750615Sobrien/* Nonzero if generating code to profile program flow graph arcs.  */
38850615Sobrien
38950615Sobrienint profile_arc_flag = 0;
39050615Sobrien
39150615Sobrien/* Nonzero if generating info for gcov to calculate line test coverage.  */
39250615Sobrien
39350615Sobrienint flag_test_coverage = 0;
39450615Sobrien
39550615Sobrien/* Nonzero indicates that branch taken probabilities should be calculated.  */
39650615Sobrien
39750615Sobrienint flag_branch_probabilities = 0;
39850615Sobrien
39990282Sobrien/* Nonzero if basic blocks should be reordered.  */
40090282Sobrien
40190282Sobrienint flag_reorder_blocks = 0;
40290282Sobrien
40390282Sobrien/* Nonzero if registers should be renamed.  */
40490282Sobrien
40590282Sobrienint flag_rename_registers = 0;
40690282Sobrienint flag_cprop_registers = 0;
40790282Sobrien
40818334Speter/* Nonzero for -pedantic switch: warn about anything
40918334Speter   that standard spec forbids.  */
41018334Speter
41118334Speterint pedantic = 0;
41218334Speter
41318334Speter/* Temporarily suppress certain warnings.
41418334Speter   This is set while reading code from a system header file.  */
41518334Speter
41618334Speterint in_system_header = 0;
41718334Speter
41890282Sobrien/* Don't print functions as they are compiled.  -quiet.  */
41918334Speter
42090282Sobrienint quiet_flag = 0;
42118334Speter
42290282Sobrien/* Print times taken by the various passes.  -ftime-report.  */
42318334Speter
42490282Sobrienint time_report = 0;
42590282Sobrien
42690282Sobrien/* Print memory still in use at end of compilation (which may have little
42790282Sobrien   to do with peak memory consumption).  -fmem-report.  */
42890282Sobrien
42990282Sobrienint mem_report = 0;
43090282Sobrien
43190282Sobrien/* Non-zero means to collect statistics which might be expensive
43290282Sobrien   and to print them when we are done.  */
43390282Sobrienint flag_detailed_statistics = 0;
43490282Sobrien
43518334Speter
43618334Speter/* -f flags.  */
43718334Speter
43818334Speter/* Nonzero means `char' should be signed.  */
43918334Speter
44018334Speterint flag_signed_char;
44118334Speter
44218334Speter/* Nonzero means give an enum type only as many bytes as it needs.  */
44318334Speter
44418334Speterint flag_short_enums;
44518334Speter
44618334Speter/* Nonzero for -fcaller-saves: allocate values in regs that need to
44718334Speter   be saved across function calls, if that produces overall better code.
44818334Speter   Optional now, so people can test it.  */
44918334Speter
45018334Speter#ifdef DEFAULT_CALLER_SAVES
45118334Speterint flag_caller_saves = 1;
45218334Speter#else
45318334Speterint flag_caller_saves = 0;
45418334Speter#endif
45518334Speter
45618334Speter/* Nonzero if structures and unions should be returned in memory.
45718334Speter
45818334Speter   This should only be defined if compatibility with another compiler or
45918334Speter   with an ABI is needed, because it results in slower code.  */
46018334Speter
46118334Speter#ifndef DEFAULT_PCC_STRUCT_RETURN
46218334Speter#define DEFAULT_PCC_STRUCT_RETURN 1
46318334Speter#endif
46418334Speter
46518334Speter/* Nonzero for -fpcc-struct-return: return values the same way PCC does.  */
46618334Speter
46718334Speterint flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
46818334Speter
46918334Speter/* Nonzero for -fforce-mem: load memory value into a register
47018334Speter   before arithmetic on it.  This makes better cse but slower compilation.  */
47118334Speter
47218334Speterint flag_force_mem = 0;
47318334Speter
47418334Speter/* Nonzero for -fforce-addr: load memory address into a register before
47518334Speter   reference to memory.  This makes better cse but slower compilation.  */
47618334Speter
47718334Speterint flag_force_addr = 0;
47818334Speter
47918334Speter/* Nonzero for -fdefer-pop: don't pop args after each function call;
48018334Speter   instead save them up to pop many calls' args with one insns.  */
48118334Speter
48218334Speterint flag_defer_pop = 0;
48318334Speter
48418334Speter/* Nonzero for -ffloat-store: don't allocate floats and doubles
48518334Speter   in extended-precision registers.  */
48618334Speter
48718334Speterint flag_float_store = 0;
48818334Speter
48918334Speter/* Nonzero for -fcse-follow-jumps:
49018334Speter   have cse follow jumps to do a more extensive job.  */
49118334Speter
49218334Speterint flag_cse_follow_jumps;
49318334Speter
49418334Speter/* Nonzero for -fcse-skip-blocks:
49518334Speter   have cse follow a branch around a block.  */
49618334Speterint flag_cse_skip_blocks;
49718334Speter
49818334Speter/* Nonzero for -fexpensive-optimizations:
49918334Speter   perform miscellaneous relatively-expensive optimizations.  */
50018334Speterint flag_expensive_optimizations;
50118334Speter
50218334Speter/* Nonzero for -fthread-jumps:
50318334Speter   have jump optimize output of loop.  */
50418334Speter
50518334Speterint flag_thread_jumps;
50618334Speter
50718334Speter/* Nonzero enables strength-reduction in loop.c.  */
50818334Speter
50918334Speterint flag_strength_reduce = 0;
51018334Speter
51118334Speter/* Nonzero enables loop unrolling in unroll.c.  Only loops for which the
51218334Speter   number of iterations can be calculated at compile-time (UNROLL_COMPLETELY,
51318334Speter   UNROLL_MODULO) or at run-time (preconditioned to be UNROLL_MODULO) are
51418334Speter   unrolled.  */
51518334Speter
51618334Speterint flag_unroll_loops;
51718334Speter
51818334Speter/* Nonzero enables loop unrolling in unroll.c.  All loops are unrolled.
51918334Speter   This is generally not a win.  */
52018334Speter
52118334Speterint flag_unroll_all_loops;
52218334Speter
52390282Sobrien/* Nonzero enables prefetch optimizations for arrays in loops.  */
52490282Sobrien
52590282Sobrienint flag_prefetch_loop_arrays;
52690282Sobrien
52750615Sobrien/* Nonzero forces all invariant computations in loops to be moved
52890282Sobrien   outside the loop.  */
52950615Sobrien
53050615Sobrienint flag_move_all_movables = 0;
53150615Sobrien
53250615Sobrien/* Nonzero forces all general induction variables in loops to be
53390282Sobrien   strength reduced.  */
53450615Sobrien
53550615Sobrienint flag_reduce_all_givs = 0;
53650615Sobrien
53750615Sobrien/* Nonzero to perform full register move optimization passes.  This is the
53850615Sobrien   default for -O2.  */
53950615Sobrien
54050615Sobrienint flag_regmove = 0;
54150615Sobrien
54218334Speter/* Nonzero for -fwritable-strings:
54318334Speter   store string constants in data segment and don't uniquize them.  */
54418334Speter
54518334Speterint flag_writable_strings = 0;
54618334Speter
54718334Speter/* Nonzero means don't put addresses of constant functions in registers.
54818334Speter   Used for compiling the Unix kernel, where strange substitutions are
54918334Speter   done on the assembly output.  */
55018334Speter
55118334Speterint flag_no_function_cse = 0;
55218334Speter
55318334Speter/* Nonzero for -fomit-frame-pointer:
55418334Speter   don't make a frame pointer in simple functions that don't require one.  */
55518334Speter
55618334Speterint flag_omit_frame_pointer = 0;
55718334Speter
55850615Sobrien/* Nonzero means place each function into its own section on those platforms
55950615Sobrien   which support arbitrary section names and unlimited numbers of sections.  */
56050615Sobrien
56150615Sobrienint flag_function_sections = 0;
56250615Sobrien
56352558Sobrien/* ... and similar for data.  */
56490282Sobrien
56552558Sobrienint flag_data_sections = 0;
56652558Sobrien
56718334Speter/* Nonzero to inhibit use of define_optimization peephole opts.  */
56818334Speter
56918334Speterint flag_no_peephole = 0;
57018334Speter
57190282Sobrien/* Nonzero allows GCC to optimize sibling and tail recursive calls.  */
57218334Speter
57390282Sobrienint flag_optimize_sibling_calls = 0;
57418334Speter
57552558Sobrien/* Nonzero means the front end generally wants `errno' maintained by math
57690282Sobrien   operations, like built-in SQRT.  */
57752558Sobrien
57852558Sobrienint flag_errno_math = 1;
57952558Sobrien
58090282Sobrien/* Nonzero means that unsafe floating-point math optimizations are allowed
58190282Sobrien   for the sake of speed.  IEEE compliance is not guaranteed, and operations
58290282Sobrien   are allowed to assume that their arguments and results are "normal"
58390282Sobrien   (e.g., nonnegative for SQRT).  */
58490282Sobrien
58590282Sobrienint flag_unsafe_math_optimizations = 0;
58690282Sobrien
58790282Sobrien/* Zero means that floating-point math operations cannot generate a
58890282Sobrien   (user-visible) trap.  This is the case, for example, in nonstop
58990282Sobrien   IEEE 754 arithmetic.  */
59090282Sobrien
59190282Sobrienint flag_trapping_math = 1;
59290282Sobrien
59352558Sobrien/* 0 means straightforward implementation of complex divide acceptable.
59452558Sobrien   1 means wide ranges of inputs must work for complex divide.
59590282Sobrien   2 means C99-like requirements for complex divide (not yet implemented).  */
59652558Sobrien
59752558Sobrienint flag_complex_divide_method = 0;
59852558Sobrien
59918334Speter/* Nonzero means all references through pointers are volatile.  */
60018334Speter
60118334Speterint flag_volatile;
60218334Speter
60352558Sobrien/* Nonzero means treat all global and extern variables as volatile.  */
60418334Speter
60518334Speterint flag_volatile_global;
60618334Speter
60752558Sobrien/* Nonzero means treat all static variables as volatile.  */
60852558Sobrien
60952558Sobrienint flag_volatile_static;
61052558Sobrien
61118334Speter/* Nonzero means just do syntax checking; don't output anything.  */
61218334Speter
61318334Speterint flag_syntax_only = 0;
61418334Speter
61550615Sobrien/* Nonzero means perform global cse.  */
61650615Sobrien
61750615Sobrienstatic int flag_gcse;
61850615Sobrien
61990282Sobrien/* Nonzero means to use global dataflow analysis to eliminate
62090282Sobrien   useless null pointer tests.  */
62190282Sobrien
62290282Sobrienstatic int flag_delete_null_pointer_checks;
62390282Sobrien
62490282Sobrien/* Nonzero means to do the enhanced load motion during gcse, which trys
62590282Sobrien   to hoist loads by not killing them when a store to the same location
62690282Sobrien   is seen.  */
62790282Sobrien
62890282Sobrienint flag_gcse_lm = 1;
62990282Sobrien
63090282Sobrien/* Nonzero means to perform store motion after gcse, which will try to
63190282Sobrien   move stores closer to the exit block.  Its not very effective without
63290282Sobrien   flag_gcse_lm.  */
63390282Sobrien
63490282Sobrienint flag_gcse_sm = 1;
63590282Sobrien
63618334Speter/* Nonzero means to rerun cse after loop optimization.  This increases
63718334Speter   compilation time about 20% and picks up a few more common expressions.  */
63818334Speter
63918334Speterstatic int flag_rerun_cse_after_loop;
64018334Speter
64150615Sobrien/* Nonzero means to run loop optimizations twice.  */
64250615Sobrien
64350615Sobrienint flag_rerun_loop_opt;
64450615Sobrien
64518334Speter/* Nonzero for -finline-functions: ok to inline functions that look like
64618334Speter   good inline candidates.  */
64718334Speter
64818334Speterint flag_inline_functions;
64918334Speter
65018334Speter/* Nonzero for -fkeep-inline-functions: even if we make a function
65118334Speter   go inline everywhere, keep its definition around for debugging
65218334Speter   purposes.  */
65318334Speter
65418334Speterint flag_keep_inline_functions;
65518334Speter
65618334Speter/* Nonzero means that functions will not be inlined.  */
65718334Speter
65896289Sobrienint flag_no_inline = 2;
65918334Speter
66096289Sobrien/* Nonzero means that we don't want inlining by virtue of -fno-inline,
66196289Sobrien   not just because the tree inliner turned us off.  */
66296289Sobrien
66396289Sobrienint flag_really_no_inline = 2;
66496289Sobrien
66550615Sobrien/* Nonzero means that we should emit static const variables
66650615Sobrien   regardless of whether or not optimization is turned on.  */
66750615Sobrien
66850615Sobrienint flag_keep_static_consts = 1;
66950615Sobrien
67018334Speter/* Nonzero means we should be saving declaration info into a .X file.  */
67118334Speter
67218334Speterint flag_gen_aux_info = 0;
67318334Speter
67418334Speter/* Specified name of aux-info file.  */
67518334Speter
67618334Speterstatic char *aux_info_file_name;
67718334Speter
67818334Speter/* Nonzero means make the text shared if supported.  */
67918334Speter
68018334Speterint flag_shared_data;
68118334Speter
68218334Speter/* Nonzero means schedule into delayed branch slots if supported.  */
68318334Speter
68418334Speterint flag_delayed_branch;
68518334Speter
68618334Speter/* Nonzero if we are compiling pure (sharable) code.
68718334Speter   Value is 1 if we are doing reasonable (i.e. simple
68818334Speter   offset into offset table) pic.  Value is 2 if we can
68918334Speter   only perform register offsets.  */
69018334Speter
69118334Speterint flag_pic;
69218334Speter
69350615Sobrien/* Nonzero means generate extra code for exception handling and enable
69450615Sobrien   exception handling.  */
69518334Speter
69650615Sobrienint flag_exceptions;
69750615Sobrien
69890282Sobrien/* Nonzero means generate frame unwind info table when supported.  */
69950615Sobrien
70090282Sobrienint flag_unwind_tables = 0;
70150615Sobrien
70290282Sobrien/* Nonzero means generate frame unwind info table exact at each insn boundary */
70390282Sobrien
70490282Sobrienint flag_asynchronous_unwind_tables = 0;
70590282Sobrien
70650615Sobrien/* Nonzero means don't place uninitialized global data in common storage
70750615Sobrien   by default.  */
70850615Sobrien
70918334Speterint flag_no_common;
71018334Speter
71118334Speter/* Nonzero means pretend it is OK to examine bits of target floats,
71218334Speter   even if that isn't true.  The resulting code will have incorrect constants,
71318334Speter   but the same series of instructions that the native compiler would make.  */
71418334Speter
71518334Speterint flag_pretend_float;
71618334Speter
71718334Speter/* Nonzero means change certain warnings into errors.
71818334Speter   Usually these are warnings about failure to conform to some standard.  */
71918334Speter
72018334Speterint flag_pedantic_errors = 0;
72118334Speter
72218334Speter/* flag_schedule_insns means schedule insns within basic blocks (before
72318334Speter   local_alloc).
72418334Speter   flag_schedule_insns_after_reload means schedule insns after
72518334Speter   global_alloc.  */
72618334Speter
72718334Speterint flag_schedule_insns = 0;
72818334Speterint flag_schedule_insns_after_reload = 0;
72918334Speter
73050615Sobrien/* The following flags have effect only for scheduling before register
73150615Sobrien   allocation:
73250615Sobrien
73350615Sobrien   flag_schedule_interblock means schedule insns accross basic blocks.
73450615Sobrien   flag_schedule_speculative means allow speculative motion of non-load insns.
73550615Sobrien   flag_schedule_speculative_load means allow speculative motion of some
73650615Sobrien   load insns.
73750615Sobrien   flag_schedule_speculative_load_dangerous allows speculative motion of more
73850615Sobrien   load insns.  */
73950615Sobrien
74050615Sobrienint flag_schedule_interblock = 1;
74150615Sobrienint flag_schedule_speculative = 1;
74250615Sobrienint flag_schedule_speculative_load = 0;
74350615Sobrienint flag_schedule_speculative_load_dangerous = 0;
74450615Sobrien
74590282Sobrienint flag_single_precision_constant;
74650615Sobrien
74790282Sobrien/* flag_branch_on_count_reg means try to replace add-1,compare,branch tupple
74890282Sobrien   by a cheaper branch on a count register.  */
74990282Sobrienint flag_branch_on_count_reg = 1;
75090282Sobrien
75118334Speter/* -finhibit-size-directive inhibits output of .size for ELF.
75290282Sobrien   This is used only for compiling crtstuff.c,
75318334Speter   and it may be extended to other effects
75418334Speter   needed for crtstuff.c on other systems.  */
75518334Speterint flag_inhibit_size_directive = 0;
75618334Speter
75718334Speter/* -fverbose-asm causes extra commentary information to be produced in
75818334Speter   the generated assembly code (to make it more readable).  This option
75918334Speter   is generally only of use to those who actually need to read the
76050615Sobrien   generated assembly code (perhaps while debugging the compiler itself).
76150615Sobrien   -fno-verbose-asm, the default, causes the extra information
76250615Sobrien   to be omitted and is useful when comparing two assembler files.  */
76318334Speter
76418334Speterint flag_verbose_asm = 0;
76518334Speter
76650615Sobrien/* -dA causes debug commentary information to be produced in
76750615Sobrien   the generated assembly code (to make it more readable).  This option
76850615Sobrien   is generally only of use to those who actually need to read the
76950615Sobrien   generated assembly code (perhaps while debugging the compiler itself).
77050615Sobrien   Currently, this switch is only used by dwarfout.c; however, it is intended
77150615Sobrien   to be a catchall for printing debug information in the assembler file.  */
77250615Sobrien
77350615Sobrienint flag_debug_asm = 0;
77450615Sobrien
77590282Sobrien/* -dP causes the rtl to be emitted as a comment in assembly.  */
77690282Sobrien
77790282Sobrienint flag_dump_rtl_in_asm = 0;
77890282Sobrien
77918334Speter/* -fgnu-linker specifies use of the GNU linker for initializations.
78018334Speter   (Or, more generally, a linker that handles initializations.)
78118334Speter   -fno-gnu-linker says that collect2 will be used.  */
78218334Speter#ifdef USE_COLLECT2
78318334Speterint flag_gnu_linker = 0;
78418334Speter#else
78518334Speterint flag_gnu_linker = 1;
78618334Speter#endif
78718334Speter
78890282Sobrien/* Enable SSA.  */
78990282Sobrienint flag_ssa = 0;
79090282Sobrien
79190282Sobrien/* Enable ssa conditional constant propagation.  */
79290282Sobrienint flag_ssa_ccp = 0;
79390282Sobrien
79490282Sobrien/* Enable ssa aggressive dead code elimination.  */
79590282Sobrienint flag_ssa_dce = 0;
79690282Sobrien
79790282Sobrien/* Tag all structures with __attribute__(packed).  */
79818334Speterint flag_pack_struct = 0;
79918334Speter
80038510Sbde/* Nonzero means that -Wformat accepts certain system-dependent formats.  */
80138510Sbdeint flag_format_extensions = 0;
80238510Sbde
80350615Sobrien/* Emit code to check for stack overflow; also may cause large objects
80450615Sobrien   to be allocated dynamically.  */
80550615Sobrienint flag_stack_check;
80650615Sobrien
80790282Sobrien/* When non-NULL, indicates that whenever space is allocated on the
80890282Sobrien   stack, the resulting stack pointer must not pass this
80990282Sobrien   address---that is, for stacks that grow downward, the stack pointer
81090282Sobrien   must always be greater than or equal to this address; for stacks
81190282Sobrien   that grow upward, the stack pointer must be less than this address.
81290282Sobrien   At present, the rtx may be either a REG or a SYMBOL_REF, although
81390282Sobrien   the support provided depends on the backend.  */
81490282Sobrienrtx stack_limit_rtx;
81550615Sobrien
81650615Sobrien/* 0 if pointer arguments may alias each other.  True in C.
81750615Sobrien   1 if pointer arguments may not alias each other but may alias
81850615Sobrien   global variables.
81950615Sobrien   2 if pointer arguments may not alias each other and may not
82050615Sobrien   alias global variables.  True in Fortran.
82150615Sobrien   This defaults to 0 for C.  */
82250615Sobrienint flag_argument_noalias = 0;
82350615Sobrien
82450615Sobrien/* Nonzero if we should do (language-dependent) alias analysis.
82550615Sobrien   Typically, this analysis will assume that expressions of certain
82650615Sobrien   types do not alias expressions of certain other types.  Only used
82750615Sobrien   if alias analysis (in general) is enabled.  */
82850615Sobrienint flag_strict_aliasing = 0;
82950615Sobrien
83052558Sobrien/* Instrument functions with calls at entry and exit, for profiling.  */
83152558Sobrienint flag_instrument_function_entry_exit = 0;
83250615Sobrien
83352558Sobrien/* Nonzero means ignore `#ident' directives.  0 means handle them.
83452558Sobrien   On SVR4 targets, it also controls whether or not to emit a
83552558Sobrien   string identifying the compiler.  */
83650615Sobrien
83752558Sobrienint flag_no_ident = 0;
83852558Sobrien
83990282Sobrien/* This will perform a peephole pass before sched2.  */
84090282Sobrienint flag_peephole2 = 0;
84190282Sobrien
84290282Sobrien/* This will try to guess branch probabilities.  */
84390282Sobrienint flag_guess_branch_prob = 0;
84490282Sobrien
84590282Sobrien/* -fbounded-pointers causes gcc to compile pointers as composite
84690282Sobrien   objects occupying three words: the pointer value, the base address
84790282Sobrien   of the referent object, and the address immediately beyond the end
84890282Sobrien   of the referent object.  The base and extent allow us to perform
84990282Sobrien   runtime bounds checking.  -fbounded-pointers implies -fcheck-bounds.  */
85090282Sobrienint flag_bounded_pointers = 0;
85190282Sobrien
85290282Sobrien/* -fcheck-bounds causes gcc to generate array bounds checks.
85390282Sobrien   For C, C++: defaults to value of flag_bounded_pointers.
85490282Sobrien   For ObjC: defaults to off.
85590282Sobrien   For Java: defaults to on.
85690282Sobrien   For Fortran: defaults to off.
85790282Sobrien   For CHILL: defaults to off.  */
85890282Sobrienint flag_bounds_check = 0;
85990282Sobrien
86090282Sobrien/* This will attempt to merge constant section constants, if 1 only
86190282Sobrien   string constants and constants from constant pool, if 2 also constant
86290282Sobrien   variables.  */
86390282Sobrienint flag_merge_constants = 1;
86490282Sobrien
86590282Sobrien/* If one, renumber instruction UIDs to reduce the number of
86690282Sobrien   unused UIDs if there are a lot of instructions.  If greater than
86790282Sobrien   one, unconditionally renumber instruction UIDs.  */
86890282Sobrienint flag_renumber_insns = 1;
86990282Sobrien
87090282Sobrien/* Values of the -falign-* flags: how much to align labels in code.
87190282Sobrien   0 means `use default', 1 means `don't align'.
87290282Sobrien   For each variable, there is an _log variant which is the power
87390282Sobrien   of two not less than the variable, for .align output.  */
87490282Sobrien
87590282Sobrienint align_loops;
87690282Sobrienint align_loops_log;
87790282Sobrienint align_loops_max_skip;
87890282Sobrienint align_jumps;
87990282Sobrienint align_jumps_log;
88090282Sobrienint align_jumps_max_skip;
88190282Sobrienint align_labels;
88290282Sobrienint align_labels_log;
88390282Sobrienint align_labels_max_skip;
88490282Sobrienint align_functions;
88590282Sobrienint align_functions_log;
88690282Sobrien
88750615Sobrien/* Table of supported debugging formats.  */
88890282Sobrienstatic const struct
88950615Sobrien{
89090282Sobrien  const char *const arg;
89150615Sobrien  /* Since PREFERRED_DEBUGGING_TYPE isn't necessarily a
89250615Sobrien     constant expression, we use NO_DEBUG in its place.  */
89390282Sobrien  const enum debug_info_type debug_type;
89490282Sobrien  const int use_extensions_p;
89590282Sobrien  const char *const description;
89650615Sobrien} *da,
89750615Sobriendebug_args[] =
89850615Sobrien{
89990282Sobrien  { "",       NO_DEBUG, DEFAULT_GDB_EXTENSIONS,
90090282Sobrien    N_("Generate debugging info in default format") },
90190282Sobrien  { "gdb",    NO_DEBUG, 1, N_("Generate debugging info in default extended format") },
90250615Sobrien#ifdef DBX_DEBUGGING_INFO
90390282Sobrien  { "stabs",  DBX_DEBUG, 0, N_("Generate STABS format debug info") },
90490282Sobrien  { "stabs+", DBX_DEBUG, 1, N_("Generate extended STABS format debug info") },
90550615Sobrien#endif
90650615Sobrien#ifdef DWARF_DEBUGGING_INFO
90790282Sobrien  { "dwarf",  DWARF_DEBUG, 0, N_("Generate DWARF-1 format debug info") },
90890282Sobrien  { "dwarf+", DWARF_DEBUG, 1,
90990282Sobrien    N_("Generate extended DWARF-1 format debug info") },
91050615Sobrien#endif
91150615Sobrien#ifdef DWARF2_DEBUGGING_INFO
91290282Sobrien  { "dwarf-2", DWARF2_DEBUG, 0, N_("Generate DWARF-2 debug info") },
91350615Sobrien#endif
91450615Sobrien#ifdef XCOFF_DEBUGGING_INFO
91590282Sobrien  { "xcoff",  XCOFF_DEBUG, 0, N_("Generate XCOFF format debug info") },
91690282Sobrien  { "xcoff+", XCOFF_DEBUG, 1, N_("Generate extended XCOFF format debug info") },
91750615Sobrien#endif
91850615Sobrien#ifdef SDB_DEBUGGING_INFO
91990282Sobrien  { "coff", SDB_DEBUG, 0, N_("Generate COFF format debug info") },
92050615Sobrien#endif
92196289Sobrien#ifdef VMS_DEBUGGING_INFO
92296289Sobrien  { "vms", VMS_DEBUG, 0, N_("Generate VMS format debug info") },
92396289Sobrien#endif
92452558Sobrien  { 0, 0, 0, 0 }
92550615Sobrien};
92650615Sobrien
92750615Sobrientypedef struct
92850615Sobrien{
92990282Sobrien  const char *const string;
93090282Sobrien  int *const variable;
93190282Sobrien  const int on_value;
93290282Sobrien  const char *const description;
93350615Sobrien}
93450615Sobrienlang_independent_options;
93550615Sobrien
93690282Sobrienint flag_trapv = 0;
93790282Sobrien
93852558Sobrien/* Add or remove a leading underscore from user symbols.  */
93952558Sobrienint flag_leading_underscore = -1;
94052558Sobrien
94152558Sobrien/* The user symbol prefix after having resolved same.  */
94252558Sobrienconst char *user_label_prefix;
94352558Sobrien
94490282Sobrienstatic const param_info lang_independent_params[] = {
94590282Sobrien#define DEFPARAM(ENUM, OPTION, HELP, DEFAULT) \
94690282Sobrien  { OPTION, DEFAULT, HELP },
94790282Sobrien#include "params.def"
94890282Sobrien#undef DEFPARAM
94990282Sobrien  { NULL, 0, NULL }
95090282Sobrien};
95190282Sobrien
95252558Sobrien/* A default for same.  */
95352558Sobrien#ifndef USER_LABEL_PREFIX
95452558Sobrien#define USER_LABEL_PREFIX ""
95552558Sobrien#endif
95652558Sobrien
95718334Speter/* Table of language-independent -f options.
95818334Speter   STRING is the option name.  VARIABLE is the address of the variable.
95918334Speter   ON_VALUE is the value to store in VARIABLE
96018334Speter    if `-fSTRING' is seen as an option.
96118334Speter   (If `-fno-STRING' is seen as an option, the opposite value is stored.)  */
96218334Speter
96390282Sobrienstatic const lang_independent_options f_options[] =
96418334Speter{
96590282Sobrien  {"format-extensions", &flag_format_extensions, 1,
96690282Sobrien   N_("-Wformat accepts certain FreeBSD system-dependent formats") },
96790282Sobrien  {"eliminate-dwarf2-dups", &flag_eliminate_dwarf2_dups, 1,
96890282Sobrien   N_("Perform DWARF2 duplicate elimination") },
96950615Sobrien  {"float-store", &flag_float_store, 1,
97090282Sobrien   N_("Do not store floats in registers") },
97150615Sobrien  {"volatile", &flag_volatile, 1,
97290282Sobrien   N_("Consider all mem refs through pointers as volatile") },
97350615Sobrien  {"volatile-global", &flag_volatile_global, 1,
97490282Sobrien   N_("Consider all mem refs to global data to be volatile") },
97552558Sobrien  {"volatile-static", &flag_volatile_static, 1,
97690282Sobrien   N_("Consider all mem refs to static data to be volatile") },
97750615Sobrien  {"defer-pop", &flag_defer_pop, 1,
97890282Sobrien   N_("Defer popping functions args from stack until later") },
97950615Sobrien  {"omit-frame-pointer", &flag_omit_frame_pointer, 1,
98090282Sobrien   N_("When possible do not generate stack frames") },
98190282Sobrien  {"optimize-sibling-calls", &flag_optimize_sibling_calls, 1,
98290282Sobrien   N_("Optimize sibling and tail recursive calls") },
98350615Sobrien  {"cse-follow-jumps", &flag_cse_follow_jumps, 1,
98490282Sobrien   N_("When running CSE, follow jumps to their targets") },
98550615Sobrien  {"cse-skip-blocks", &flag_cse_skip_blocks, 1,
98690282Sobrien   N_("When running CSE, follow conditional jumps") },
98750615Sobrien  {"expensive-optimizations", &flag_expensive_optimizations, 1,
98890282Sobrien   N_("Perform a number of minor, expensive optimizations") },
98950615Sobrien  {"thread-jumps", &flag_thread_jumps, 1,
99090282Sobrien   N_("Perform jump threading optimizations") },
99150615Sobrien  {"strength-reduce", &flag_strength_reduce, 1,
99290282Sobrien   N_("Perform strength reduction optimizations") },
99350615Sobrien  {"unroll-loops", &flag_unroll_loops, 1,
99490282Sobrien   N_("Perform loop unrolling when iteration count is known") },
99550615Sobrien  {"unroll-all-loops", &flag_unroll_all_loops, 1,
99690282Sobrien   N_("Perform loop unrolling for all loops") },
99790282Sobrien  {"prefetch-loop-arrays", &flag_prefetch_loop_arrays, 1,
99890282Sobrien   N_("Generate prefetch instructions, if available, for arrays in loops") },
99950615Sobrien  {"move-all-movables", &flag_move_all_movables, 1,
100090282Sobrien   N_("Force all loop invariant computations out of loops") },
100150615Sobrien  {"reduce-all-givs", &flag_reduce_all_givs, 1,
100290282Sobrien   N_("Strength reduce all loop general induction variables") },
100350615Sobrien  {"writable-strings", &flag_writable_strings, 1,
100490282Sobrien   N_("Store strings in writable data section") },
100550615Sobrien  {"peephole", &flag_no_peephole, 0,
100690282Sobrien   N_("Enable machine specific peephole optimizations") },
100750615Sobrien  {"force-mem", &flag_force_mem, 1,
100890282Sobrien   N_("Copy memory operands into registers before using") },
100950615Sobrien  {"force-addr", &flag_force_addr, 1,
101090282Sobrien   N_("Copy memory address constants into regs before using") },
101150615Sobrien  {"function-cse", &flag_no_function_cse, 0,
101290282Sobrien   N_("Allow function addresses to be held in registers") },
101350615Sobrien  {"inline-functions", &flag_inline_functions, 1,
101490282Sobrien   N_("Integrate simple functions into their callers") },
101550615Sobrien  {"keep-inline-functions", &flag_keep_inline_functions, 1,
101690282Sobrien   N_("Generate code for funcs even if they are fully inlined") },
101750615Sobrien  {"inline", &flag_no_inline, 0,
101890282Sobrien   N_("Pay attention to the 'inline' keyword") },
101950615Sobrien  {"keep-static-consts", &flag_keep_static_consts, 1,
102090282Sobrien   N_("Emit static const variables even if they are not used") },
102150615Sobrien  {"syntax-only", &flag_syntax_only, 1,
102290282Sobrien   N_("Check for syntax errors, then stop") },
102350615Sobrien  {"shared-data", &flag_shared_data, 1,
102490282Sobrien   N_("Mark data as shared rather than private") },
102550615Sobrien  {"caller-saves", &flag_caller_saves, 1,
102690282Sobrien   N_("Enable saving registers around function calls") },
102750615Sobrien  {"pcc-struct-return", &flag_pcc_struct_return, 1,
102890282Sobrien   N_("Return 'short' aggregates in memory, not registers") },
102950615Sobrien  {"reg-struct-return", &flag_pcc_struct_return, 0,
103090282Sobrien   N_("Return 'short' aggregates in registers") },
103150615Sobrien  {"delayed-branch", &flag_delayed_branch, 1,
103290282Sobrien   N_("Attempt to fill delay slots of branch instructions") },
103350615Sobrien  {"gcse", &flag_gcse, 1,
103490282Sobrien   N_("Perform the global common subexpression elimination") },
103590282Sobrien  {"gcse-lm", &flag_gcse_lm, 1,
103690282Sobrien   N_("Perform enhanced load motion during global subexpression elimination") },
103790282Sobrien  {"gcse-sm", &flag_gcse_sm, 1,
103890282Sobrien   N_("Perform store motion after global subexpression elimination") },
103950615Sobrien  {"rerun-cse-after-loop", &flag_rerun_cse_after_loop, 1,
104090282Sobrien   N_("Run CSE pass after loop optimizations") },
104150615Sobrien  {"rerun-loop-opt", &flag_rerun_loop_opt, 1,
104290282Sobrien   N_("Run the loop optimizer twice") },
104390282Sobrien  {"delete-null-pointer-checks", &flag_delete_null_pointer_checks, 1,
104490282Sobrien   N_("Delete useless null pointer checks") },
104550615Sobrien  {"pretend-float", &flag_pretend_float, 1,
104690282Sobrien   N_("Pretend that host and target use the same FP format") },
104750615Sobrien  {"schedule-insns", &flag_schedule_insns, 1,
104890282Sobrien   N_("Reschedule instructions before register allocation") },
104950615Sobrien  {"schedule-insns2", &flag_schedule_insns_after_reload, 1,
105090282Sobrien   N_("Reschedule instructions after register allocation") },
105150615Sobrien  {"sched-interblock",&flag_schedule_interblock, 1,
105290282Sobrien   N_("Enable scheduling across basic blocks") },
105350615Sobrien  {"sched-spec",&flag_schedule_speculative, 1,
105490282Sobrien   N_("Allow speculative motion of non-loads") },
105550615Sobrien  {"sched-spec-load",&flag_schedule_speculative_load, 1,
105690282Sobrien   N_("Allow speculative motion of some loads") },
105750615Sobrien  {"sched-spec-load-dangerous",&flag_schedule_speculative_load_dangerous, 1,
105890282Sobrien   N_("Allow speculative motion of more loads") },
105950615Sobrien  {"branch-count-reg",&flag_branch_on_count_reg, 1,
106090282Sobrien   N_("Replace add,compare,branch with branch on count reg") },
106150615Sobrien  {"pic", &flag_pic, 1,
106290282Sobrien   N_("Generate position independent code, if possible") },
106350615Sobrien  {"PIC", &flag_pic, 2, ""},
106450615Sobrien  {"exceptions", &flag_exceptions, 1,
106590282Sobrien   N_("Enable exception handling") },
106690282Sobrien  {"unwind-tables", &flag_unwind_tables, 1,
106790282Sobrien   N_("Just generate unwind tables for exception handling") },
106890282Sobrien  {"asynchronous-unwind-tables", &flag_asynchronous_unwind_tables, 1,
106990282Sobrien   N_("Generate unwind tables exact at each instruction boundary") },
107090282Sobrien  {"non-call-exceptions", &flag_non_call_exceptions, 1,
107190282Sobrien   N_("Support synchronous non-call exceptions") },
107250615Sobrien  {"profile-arcs", &profile_arc_flag, 1,
107390282Sobrien   N_("Insert arc based program profiling code") },
107450615Sobrien  {"test-coverage", &flag_test_coverage, 1,
107590282Sobrien   N_("Create data files needed by gcov") },
107650615Sobrien  {"branch-probabilities", &flag_branch_probabilities, 1,
107790282Sobrien   N_("Use profiling information for branch probabilities") },
107890282Sobrien  {"reorder-blocks", &flag_reorder_blocks, 1,
107990282Sobrien   N_("Reorder basic blocks to improve code placement") },
108090282Sobrien  {"rename-registers", &flag_rename_registers, 1,
108190282Sobrien   N_("Do the register renaming optimization pass") },
108290282Sobrien  {"cprop-registers", &flag_cprop_registers, 1,
108390282Sobrien   N_("Do the register copy-propagation optimization pass") },
108450615Sobrien  {"common", &flag_no_common, 0,
108590282Sobrien   N_("Do not put uninitialized globals in the common section") },
108650615Sobrien  {"inhibit-size-directive", &flag_inhibit_size_directive, 1,
108790282Sobrien   N_("Do not generate .size directives") },
108850615Sobrien  {"function-sections", &flag_function_sections, 1,
108990282Sobrien   N_("place each function into its own section") },
109052558Sobrien  {"data-sections", &flag_data_sections, 1,
109190282Sobrien   N_("place data items into their own section") },
109250615Sobrien  {"verbose-asm", &flag_verbose_asm, 1,
109390282Sobrien   N_("Add extra commentry to assembler output") },
109450615Sobrien  {"gnu-linker", &flag_gnu_linker, 1,
109590282Sobrien   N_("Output GNU ld formatted global initializers") },
109650615Sobrien  {"regmove", &flag_regmove, 1,
109790282Sobrien   N_("Enables a register move optimization") },
109852558Sobrien  {"optimize-register-move", &flag_regmove, 1,
109990282Sobrien   N_("Do the full regmove optimization pass") },
110050615Sobrien  {"pack-struct", &flag_pack_struct, 1,
110190282Sobrien   N_("Pack structure members together without holes") },
110250615Sobrien  {"stack-check", &flag_stack_check, 1,
110390282Sobrien   N_("Insert stack checking code into the program") },
110450615Sobrien  {"argument-alias", &flag_argument_noalias, 0,
110590282Sobrien   N_("Specify that arguments may alias each other & globals") },
110650615Sobrien  {"argument-noalias", &flag_argument_noalias, 1,
110790282Sobrien   N_("Assume arguments may alias globals but not each other") },
110850615Sobrien  {"argument-noalias-global", &flag_argument_noalias, 2,
110990282Sobrien   N_("Assume arguments do not alias each other or globals") },
111050615Sobrien  {"strict-aliasing", &flag_strict_aliasing, 1,
111190282Sobrien   N_("Assume strict aliasing rules apply") },
111290282Sobrien  {"align-loops", &align_loops, 0,
111390282Sobrien   N_("Align the start of loops") },
111490282Sobrien  {"align-jumps", &align_jumps, 0,
111590282Sobrien   N_("Align labels which are only reached by jumping") },
111690282Sobrien  {"align-labels", &align_labels, 0,
111790282Sobrien   N_("Align all labels") },
111890282Sobrien  {"align-functions", &align_functions, 0,
111990282Sobrien   N_("Align the start of functions") },
112090282Sobrien  {"merge-constants", &flag_merge_constants, 1,
112190282Sobrien   N_("Attempt to merge identical constants accross compilation units") },
112290282Sobrien  {"merge-all-constants", &flag_merge_constants, 2,
112390282Sobrien   N_("Attempt to merge identical constants and constant variables") },
112452558Sobrien  {"dump-unnumbered", &flag_dump_unnumbered, 1,
112590282Sobrien   N_("Suppress output of instruction numbers and line number notes in debugging dumps") },
112652558Sobrien  {"instrument-functions", &flag_instrument_function_entry_exit, 1,
112790282Sobrien   N_("Instrument function entry/exit with profiling calls") },
112890282Sobrien  {"ssa", &flag_ssa, 1,
112990282Sobrien   N_("Enable SSA optimizations") },
113090282Sobrien  {"ssa-ccp", &flag_ssa_ccp, 1,
113190282Sobrien   N_("Enable SSA conditional constant propagation") },
113290282Sobrien  {"ssa-dce", &flag_ssa_dce, 1,
113390282Sobrien   N_("Enable aggressive SSA dead code elimination") },
113452558Sobrien  {"leading-underscore", &flag_leading_underscore, 1,
113590282Sobrien   N_("External symbols have a leading underscore") },
113652558Sobrien  {"ident", &flag_no_ident, 0,
113790282Sobrien   N_("Process #ident directives") },
113890282Sobrien  { "peephole2", &flag_peephole2, 1,
113990282Sobrien   N_("Enables an rtl peephole pass run before sched2") },
114090282Sobrien  { "guess-branch-probability", &flag_guess_branch_prob, 1,
114190282Sobrien   N_("Enables guessing of branch probabilities") },
114290282Sobrien  {"math-errno", &flag_errno_math, 1,
114390282Sobrien   N_("Set errno after built-in math functions") },
114490282Sobrien  {"trapping-math", &flag_trapping_math, 1,
114590282Sobrien   N_("Floating-point operations can trap") },
114690282Sobrien  {"unsafe-math-optimizations", &flag_unsafe_math_optimizations, 1,
114790282Sobrien   N_("Allow math optimizations that may violate IEEE or ANSI standards") },
114890282Sobrien  {"bounded-pointers", &flag_bounded_pointers, 1,
114990282Sobrien   N_("Compile pointers as triples: value, base & end") },
115090282Sobrien  {"bounds-check", &flag_bounds_check, 1,
115190282Sobrien   N_("Generate code to check bounds before dereferencing pointers and arrays") },
115290282Sobrien  {"single-precision-constant", &flag_single_precision_constant, 1,
115390282Sobrien   N_("Convert floating point constant to single precision constant") },
115490282Sobrien  {"time-report", &time_report, 1,
115590282Sobrien   N_("Report time taken by each compiler pass at end of run") },
115690282Sobrien  {"mem-report", &mem_report, 1,
115790282Sobrien   N_("Report on permanent memory allocation at end of run") },
115890282Sobrien  { "trapv", &flag_trapv, 1,
115990282Sobrien   N_("Trap for signed overflow in addition / subtraction / multiplication") },
116018334Speter};
116118334Speter
116218334Speter/* Table of language-specific options.  */
116318334Speter
116490282Sobrienstatic const struct lang_opt
116518334Speter{
116690282Sobrien  const char *const option;
116790282Sobrien  const char *const description;
116850615Sobrien}
116950615Sobriendocumented_lang_options[] =
117050615Sobrien{
117150615Sobrien  /* In order not to overload the --help output, the convention
117250615Sobrien     used here is to only describe those options which are not
117350615Sobrien     enabled by default.  */
117418334Speter
117590282Sobrien  { "-ansi",
117690282Sobrien    N_("Compile just for ISO C89") },
117750615Sobrien  { "-fallow-single-precision",
117890282Sobrien    N_("Do not promote floats to double if using -traditional") },
117990282Sobrien  { "-std= ",
118090282Sobrien    N_("Determine language standard") },
118118334Speter
118250615Sobrien  { "-fsigned-bitfields", "" },
118390282Sobrien  { "-funsigned-bitfields",
118490282Sobrien    N_("Make bit-fields by unsigned by default") },
118550615Sobrien  { "-fno-signed-bitfields", "" },
118650615Sobrien  { "-fno-unsigned-bitfields","" },
118790282Sobrien  { "-fsigned-char",
118890282Sobrien    N_("Make 'char' be signed by default") },
118990282Sobrien  { "-funsigned-char",
119090282Sobrien    N_("Make 'char' be unsigned by default") },
119150615Sobrien  { "-fno-signed-char", "" },
119250615Sobrien  { "-fno-unsigned-char", "" },
119318334Speter
119450615Sobrien  { "-ftraditional", "" },
119590282Sobrien  { "-traditional",
119690282Sobrien    N_("Attempt to support traditional K&R style C") },
119750615Sobrien  { "-fnotraditional", "" },
119850615Sobrien  { "-fno-traditional", "" },
119918334Speter
120050615Sobrien  { "-fasm", "" },
120190282Sobrien  { "-fno-asm",
120290282Sobrien    N_("Do not recognize the 'asm' keyword") },
120350615Sobrien  { "-fbuiltin", "" },
120490282Sobrien  { "-fno-builtin",
120590282Sobrien    N_("Do not recognize any built in functions") },
120690282Sobrien  { "-fhosted",
120790282Sobrien    N_("Assume normal C execution environment") },
120850615Sobrien  { "-fno-hosted", "" },
120950615Sobrien  { "-ffreestanding",
121090282Sobrien    N_("Assume that standard libraries & main might not exist") },
121150615Sobrien  { "-fno-freestanding", "" },
121290282Sobrien  { "-fcond-mismatch",
121390282Sobrien    N_("Allow different types as args of ? operator") },
121450615Sobrien  { "-fno-cond-mismatch", "" },
121590282Sobrien  { "-fdollars-in-identifiers",
121690282Sobrien    N_("Allow the use of $ inside identifiers") },
121750615Sobrien  { "-fno-dollars-in-identifiers", "" },
121890282Sobrien  { "-fpreprocessed", "" },
121990282Sobrien  { "-fno-preprocessed", "" },
122090282Sobrien  { "-fshort-double",
122190282Sobrien    N_("Use the same size for double as for float") },
122250615Sobrien  { "-fno-short-double", "" },
122390282Sobrien  { "-fshort-enums",
122490282Sobrien    N_("Use the smallest fitting integer to hold enums") },
122550615Sobrien  { "-fno-short-enums", "" },
122690282Sobrien  { "-fshort-wchar",
122790282Sobrien    N_("Override the underlying type for wchar_t to `unsigned short'") },
122890282Sobrien  { "-fno-short-wchar", "" },
122918334Speter
123090282Sobrien  { "-Wall",
123190282Sobrien    N_("Enable most warning messages") },
123250615Sobrien  { "-Wbad-function-cast",
123390282Sobrien    N_("Warn about casting functions to incompatible types") },
123450615Sobrien  { "-Wno-bad-function-cast", "" },
123552558Sobrien  { "-Wno-missing-noreturn", "" },
123690282Sobrien  { "-Wmissing-format-attribute",
123790282Sobrien    N_("Warn about functions which might be candidates for format attributes") },
123890282Sobrien  { "-Wno-missing-format-attribute", "" },
123990282Sobrien  { "-Wcast-qual",
124090282Sobrien    N_("Warn about casts which discard qualifiers") },
124150615Sobrien  { "-Wno-cast-qual", "" },
124290282Sobrien  { "-Wchar-subscripts",
124390282Sobrien    N_("Warn about subscripts whose type is 'char'") },
124450615Sobrien  { "-Wno-char-subscripts", "" },
124590282Sobrien  { "-Wcomment",
124690282Sobrien    N_("Warn if nested comments are detected") },
124752558Sobrien  { "-Wno-comment", "" },
124890282Sobrien  { "-Wcomments",
124990282Sobrien    N_("Warn if nested comments are detected") },
125052558Sobrien  { "-Wno-comments", "" },
125190282Sobrien  { "-Wconversion",
125290282Sobrien    N_("Warn about possibly confusing type conversions") },
125350615Sobrien  { "-Wno-conversion", "" },
125490282Sobrien  { "-Wformat",
125590282Sobrien    N_("Warn about printf/scanf/strftime/strfmon format anomalies") },
125650615Sobrien  { "-Wno-format", "" },
125790282Sobrien  { "-Wformat-y2k", "" },
125890282Sobrien  { "-Wno-format-y2k",
125990282Sobrien    N_("Don't warn about strftime formats yielding 2 digit years") },
126090282Sobrien  { "-Wformat-extra-args", "" },
126190282Sobrien  { "-Wno-format-extra-args",
126290282Sobrien    N_("Don't warn about too many arguments to format functions") },
126390282Sobrien  { "-Wformat-nonliteral",
126490282Sobrien    N_("Warn about non-string-literal format strings") },
126590282Sobrien  { "-Wno-format-nonliteral", "" },
126690282Sobrien  { "-Wformat-security",
126790282Sobrien    N_("Warn about possible security problems with format functions") },
126890282Sobrien  { "-Wno-format-security", "" },
126950615Sobrien  { "-Wimplicit-function-declaration",
127090282Sobrien    N_("Warn about implicit function declarations") },
127150615Sobrien  { "-Wno-implicit-function-declaration", "" },
127250615Sobrien  { "-Werror-implicit-function-declaration", "" },
127390282Sobrien  { "-Wimplicit-int",
127490282Sobrien    N_("Warn when a declaration does not specify a type") },
127550615Sobrien  { "-Wno-implicit-int", "" },
127650615Sobrien  { "-Wimplicit", "" },
127750615Sobrien  { "-Wno-implicit", "" },
127890282Sobrien  { "-Wimport",
127990282Sobrien    N_("Warn about the use of the #import directive") },
128050615Sobrien  { "-Wno-import", "" },
128150615Sobrien  { "-Wlong-long","" },
128290282Sobrien  { "-Wno-long-long",
128390282Sobrien    N_("Do not warn about using 'long long' when -pedantic") },
128490282Sobrien  { "-Wmain",
128590282Sobrien    N_("Warn about suspicious declarations of main") },
128650615Sobrien  { "-Wno-main", "" },
128750615Sobrien  { "-Wmissing-braces",
128890282Sobrien    N_("Warn about possibly missing braces around initializers") },
128950615Sobrien  { "-Wno-missing-braces", "" },
129050615Sobrien  { "-Wmissing-declarations",
129190282Sobrien    N_("Warn about global funcs without previous declarations") },
129250615Sobrien  { "-Wno-missing-declarations", "" },
129390282Sobrien  { "-Wmissing-prototypes",
129490282Sobrien    N_("Warn about global funcs without prototypes") },
129550615Sobrien  { "-Wno-missing-prototypes", "" },
129690282Sobrien  { "-Wmultichar",
129790282Sobrien    N_("Warn about use of multicharacter literals") },
129850615Sobrien  { "-Wno-multichar", "" },
129990282Sobrien  { "-Wnested-externs",
130090282Sobrien    N_("Warn about externs not at file scope level") },
130150615Sobrien  { "-Wno-nested-externs", "" },
130290282Sobrien  { "-Wparentheses",
130390282Sobrien    N_("Warn about possible missing parentheses") },
130450615Sobrien  { "-Wno-parentheses", "" },
130590282Sobrien  { "-Wsequence-point",
130690282Sobrien    N_("Warn about possible violations of sequence point rules") },
130790282Sobrien  { "-Wno-sequence-point", "" },
130890282Sobrien  { "-Wpointer-arith",
130990282Sobrien    N_("Warn about function pointer arithmetic") },
131050615Sobrien  { "-Wno-pointer-arith", "" },
131150615Sobrien  { "-Wredundant-decls",
131290282Sobrien    N_("Warn about multiple declarations of the same object") },
131350615Sobrien  { "-Wno-redundant-decls", "" },
131490282Sobrien  { "-Wsign-compare",
131590282Sobrien    N_("Warn about signed/unsigned comparisons") },
131650615Sobrien  { "-Wno-sign-compare", "" },
131790282Sobrien  { "-Wfloat-equal",
131890282Sobrien    N_("Warn about testing equality of floating point numbers") },
131990282Sobrien  { "-Wno-float-equal", "" },
132090282Sobrien  { "-Wunknown-pragmas",
132190282Sobrien    N_("Warn about unrecognized pragmas") },
132250615Sobrien  { "-Wno-unknown-pragmas", "" },
132390282Sobrien  { "-Wstrict-prototypes",
132490282Sobrien    N_("Warn about non-prototyped function decls") },
132550615Sobrien  { "-Wno-strict-prototypes", "" },
132690282Sobrien  { "-Wtraditional",
132790282Sobrien    N_("Warn about constructs whose meaning change in ISO C") },
132850615Sobrien  { "-Wno-traditional", "" },
132990282Sobrien  { "-Wtrigraphs",
133090282Sobrien    N_("Warn when trigraphs are encountered") },
133150615Sobrien  { "-Wno-trigraphs", "" },
133250615Sobrien  { "-Wundef", "" },
133350615Sobrien  { "-Wno-undef", "" },
133490282Sobrien  { "-Wwrite-strings",
133590282Sobrien    N_("Mark strings as 'const char *'") },
133650615Sobrien  { "-Wno-write-strings", "" },
133718334Speter
133850615Sobrien#define DEFINE_LANG_NAME(NAME) { NULL, NAME },
133950615Sobrien
134018334Speter#include "options.h"
134190282Sobrien
134218334Speter};
134350615Sobrien
134450615Sobrien/* Here is a table, controlled by the tm.h file, listing each -m switch
134550615Sobrien   and which bits in `target_switches' it should set or clear.
134650615Sobrien   If VALUE is positive, it is bits to set.
134750615Sobrien   If VALUE is negative, -VALUE is bits to clear.
134850615Sobrien   (The sign bit is not used so there is no confusion.)  */
134950615Sobrien
135090282Sobrienstatic const struct
135150615Sobrien{
135290282Sobrien  const char *const name;
135390282Sobrien  const int value;
135490282Sobrien  const char *const description;
135550615Sobrien}
135650615Sobrientarget_switches [] = TARGET_SWITCHES;
135750615Sobrien
135850615Sobrien/* This table is similar, but allows the switch to have a value.  */
135950615Sobrien
136050615Sobrien#ifdef TARGET_OPTIONS
136190282Sobrienstatic const struct
136250615Sobrien{
136390282Sobrien  const char *const prefix;
136490282Sobrien  const char **const variable;
136590282Sobrien  const char *const description;
136650615Sobrien}
136750615Sobrientarget_options [] = TARGET_OPTIONS;
136850615Sobrien#endif
136918334Speter
137090282Sobrien/* Options controlling warnings.  */
137118334Speter
137218334Speter/* Don't print warning messages.  -w.  */
137318334Speter
137418334Speterint inhibit_warnings = 0;
137518334Speter
137690282Sobrien/* Don't suppress warnings from system headers.  -Wsystem-headers.  */
137790282Sobrien
137890282Sobrienint warn_system_headers = 0;
137990282Sobrien
138018334Speter/* Print various extra warnings.  -W.  */
138118334Speter
138218334Speterint extra_warnings = 0;
138318334Speter
138418334Speter/* Treat warnings as errors.  -Werror.  */
138518334Speter
138618334Speterint warnings_are_errors = 0;
138718334Speter
138890282Sobrien/* Nonzero to warn about unused variables, functions et.al.  */
138918334Speter
139090282Sobrienint warn_unused_function;
139190282Sobrienint warn_unused_label;
139290282Sobrienint warn_unused_parameter;
139390282Sobrienint warn_unused_variable;
139490282Sobrienint warn_unused_value;
139518334Speter
139690282Sobrien/* Nonzero to warn about code which is never reached.  */
139790282Sobrien
139890282Sobrienint warn_notreached;
139990282Sobrien
140018334Speter/* Nonzero to warn about variables used before they are initialized.  */
140118334Speter
140218334Speterint warn_uninitialized;
140318334Speter
140490282Sobrien/* Nonzero means warn about all declarations which shadow others.  */
140518334Speter
140618334Speterint warn_shadow;
140718334Speter
140818334Speter/* Warn if a switch on an enum fails to have a case for every enum value.  */
140918334Speter
141018334Speterint warn_switch;
141118334Speter
141218334Speter/* Nonzero means warn about function definitions that default the return type
141318334Speter   or that use a null return and have a return-type other than void.  */
141418334Speter
141518334Speterint warn_return_type;
141618334Speter
141718334Speter/* Nonzero means warn about pointer casts that increase the required
141818334Speter   alignment of the target type (and might therefore lead to a crash
141918334Speter   due to a misaligned access).  */
142018334Speter
142118334Speterint warn_cast_align;
142218334Speter
142318334Speter/* Nonzero means warn about any objects definitions whose size is larger
142418334Speter   than N bytes.  Also want about function definitions whose returned
142518334Speter   values are larger than N bytes. The value N is in `larger_than_size'.  */
142690282Sobrien
142718334Speterint warn_larger_than;
142890282SobrienHOST_WIDE_INT larger_than_size;
142918334Speter
143018334Speter/* Nonzero means warn if inline function is too large.  */
143118334Speter
143218334Speterint warn_inline;
143318334Speter
143418334Speter/* Warn if a function returns an aggregate,
143518334Speter   since there are often incompatible calling conventions for doing this.  */
143618334Speter
143718334Speterint warn_aggregate_return;
143818334Speter
143990282Sobrien/* Warn if packed attribute on struct is unnecessary and inefficient.  */
144090282Sobrien
144190282Sobrienint warn_packed;
144290282Sobrien
144390282Sobrien/* Warn when gcc pads a structure to an alignment boundary.  */
144490282Sobrien
144590282Sobrienint warn_padded;
144690282Sobrien
144790282Sobrien/* Warn when an optimization pass is disabled.  */
144890282Sobrien
144990282Sobrienint warn_disabled_optimization;
145090282Sobrien
145190282Sobrien/* Warn about functions which might be candidates for attribute noreturn.  */
145290282Sobrien
145390282Sobrienint warn_missing_noreturn;
145490282Sobrien
145590282Sobrien/* Nonzero means warn about uses of __attribute__((deprecated))
145690282Sobrien   declarations.  */
145790282Sobrien
145890282Sobrienint warn_deprecated_decl = 1;
145990282Sobrien
146018334Speter/* Likewise for -W.  */
146118334Speter
146290282Sobrienstatic const lang_independent_options W_options[] =
146318334Speter{
146490282Sobrien  {"unused-function", &warn_unused_function, 1,
146590282Sobrien   N_("Warn when a function is unused") },
146690282Sobrien  {"unused-label", &warn_unused_label, 1,
146790282Sobrien   N_("Warn when a label is unused") },
146890282Sobrien  {"unused-parameter", &warn_unused_parameter, 1,
146990282Sobrien   N_("Warn when a function parameter is unused") },
147090282Sobrien  {"unused-variable", &warn_unused_variable, 1,
147190282Sobrien   N_("Warn when a variable is unused") },
147290282Sobrien  {"unused-value", &warn_unused_value, 1,
147390282Sobrien   N_("Warn when an expression value is unused") },
147490282Sobrien  {"system-headers", &warn_system_headers, 1,
147590282Sobrien   N_("Do not suppress warnings from system headers") },
147690282Sobrien  {"error", &warnings_are_errors, 1,
147790282Sobrien   N_("Treat all warnings as errors") },
147890282Sobrien  {"shadow", &warn_shadow, 1,
147990282Sobrien   N_("Warn when one local variable shadows another") },
148050615Sobrien  {"switch", &warn_switch, 1,
148190282Sobrien   N_("Warn about enumerated switches missing a specific case") },
148250615Sobrien  {"aggregate-return", &warn_aggregate_return, 1,
148390282Sobrien   N_("Warn about returning structures, unions or arrays") },
148450615Sobrien  {"cast-align", &warn_cast_align, 1,
148590282Sobrien   N_("Warn about pointer casts which increase alignment") },
148690282Sobrien  {"unreachable-code", &warn_notreached, 1,
148790282Sobrien   N_("Warn about code that will never be executed") },
148850615Sobrien  {"uninitialized", &warn_uninitialized, 1,
148990282Sobrien   N_("Warn about uninitialized automatic variables") },
149050615Sobrien  {"inline", &warn_inline, 1,
149190282Sobrien   N_("Warn when an inlined function cannot be inlined") },
149290282Sobrien  {"packed", &warn_packed, 1,
149390282Sobrien   N_("Warn when the packed attribute has no effect on struct layout") },
149490282Sobrien  {"padded", &warn_padded, 1,
149590282Sobrien   N_("Warn when padding is required to align struct members") },
149690282Sobrien  {"disabled-optimization", &warn_disabled_optimization, 1,
149790282Sobrien   N_("Warn when an optimization pass is disabled") },
149890282Sobrien  {"deprecated-declarations", &warn_deprecated_decl, 1,
149990282Sobrien   N_("Warn about uses of __attribute__((deprecated)) declarations") },
150090282Sobrien  {"missing-noreturn", &warn_missing_noreturn, 1,
150190282Sobrien   N_("Warn about functions which might be candidates for attribute noreturn") }
150218334Speter};
150390282Sobrien
150490282Sobrienvoid
150590282Sobrienset_Wunused (setting)
150690282Sobrien     int setting;
150790282Sobrien{
150890282Sobrien  warn_unused_function = setting;
150990282Sobrien  warn_unused_label = setting;
151090282Sobrien  /* Unused function parameter warnings are reported when either ``-W
151190282Sobrien     -Wunused'' or ``-Wunused-parameter'' is specified.  Differentiate
151290282Sobrien     -Wunused by setting WARN_UNUSED_PARAMETER to -1.  */
151390282Sobrien  if (!setting)
151490282Sobrien    warn_unused_parameter = 0;
151590282Sobrien  else if (!warn_unused_parameter)
151690282Sobrien    warn_unused_parameter = -1;
151790282Sobrien  warn_unused_variable = setting;
151890282Sobrien  warn_unused_value = setting;
151990282Sobrien}
152090282Sobrien
152190282Sobrien/* The following routines are useful in setting all the flags that
152290282Sobrien   -ffast-math and -fno-fast-math imply.  */
152390282Sobrien
152490282Sobrienvoid
152590282Sobrienset_fast_math_flags ()
152690282Sobrien{
152790282Sobrien  flag_trapping_math = 0;
152890282Sobrien  flag_unsafe_math_optimizations = 1;
152990282Sobrien  flag_errno_math = 0;
153090282Sobrien}
153190282Sobrien
153290282Sobrienvoid
153390282Sobrienset_no_fast_math_flags ()
153490282Sobrien{
153590282Sobrien  flag_trapping_math = 1;
153690282Sobrien  flag_unsafe_math_optimizations = 0;
153790282Sobrien  flag_errno_math = 1;
153890282Sobrien}
153990282Sobrien
154018334Speter
154118334Speter/* Output files for assembler code (real compiler output)
154218334Speter   and debugging dumps.  */
154318334Speter
154418334SpeterFILE *asm_out_file;
154518334SpeterFILE *aux_info_file;
154650615SobrienFILE *rtl_dump_file = NULL;
154718334Speter
154852558Sobrien/* Decode the string P as an integral parameter.
154952558Sobrien   If the string is indeed an integer return its numeric value else
155052558Sobrien   issue an Invalid Option error for the option PNAME and return DEFVAL.
155190282Sobrien   If PNAME is zero just return DEFVAL, do not call error.  */
155290282Sobrien
155352558Sobrienint
155452558Sobrienread_integral_parameter (p, pname, defval)
155552558Sobrien     const char *p;
155652558Sobrien     const char *pname;
155752558Sobrien     const int  defval;
155852558Sobrien{
155952558Sobrien  const char *endp = p;
156052558Sobrien
156152558Sobrien  while (*endp)
156252558Sobrien    {
156390282Sobrien      if (ISDIGIT (*endp))
156452558Sobrien	endp++;
156552558Sobrien      else
156652558Sobrien	break;
156752558Sobrien    }
156852558Sobrien
156952558Sobrien  if (*endp != 0)
157052558Sobrien    {
157152558Sobrien      if (pname != 0)
157290282Sobrien	error ("invalid option `%s'", pname);
157352558Sobrien      return defval;
157452558Sobrien    }
157552558Sobrien
157652558Sobrien  return atoi (p);
157752558Sobrien}
157852558Sobrien
157918334Speter
158018334Speter/* This is the default decl_printable_name function.  */
158118334Speter
158290282Sobrienstatic const char *
158350615Sobriendecl_name (decl, verbosity)
158418334Speter     tree decl;
158552558Sobrien     int verbosity ATTRIBUTE_UNUSED;
158618334Speter{
158718334Speter  return IDENTIFIER_POINTER (DECL_NAME (decl));
158818334Speter}
158918334Speter
159018334Speter
159118334Speter/* This calls abort and is used to avoid problems when abort if a macro.
159218334Speter   It is used when we need to pass the address of abort.  */
159318334Speter
159418334Spetervoid
159518334Speterdo_abort ()
159618334Speter{
159718334Speter  abort ();
159818334Speter}
159918334Speter
160018334Speter/* When `malloc.c' is compiled with `rcheck' defined,
160118334Speter   it calls this function to report clobberage.  */
160218334Speter
160318334Spetervoid
160418334Speterbotch (s)
160590282Sobrien     const char *s ATTRIBUTE_UNUSED;
160618334Speter{
160718334Speter  abort ();
160818334Speter}
160918334Speter
161018334Speter/* Return the logarithm of X, base 2, considering X unsigned,
161118334Speter   if X is a power of 2.  Otherwise, returns -1.
161218334Speter
161318334Speter   This should be used via the `exact_log2' macro.  */
161418334Speter
161518334Speterint
161618334Speterexact_log2_wide (x)
161790282Sobrien     unsigned HOST_WIDE_INT x;
161818334Speter{
161990282Sobrien  int log = 0;
162018334Speter  /* Test for 0 or a power of 2.  */
162118334Speter  if (x == 0 || x != (x & -x))
162218334Speter    return -1;
162318334Speter  while ((x >>= 1) != 0)
162418334Speter    log++;
162518334Speter  return log;
162618334Speter}
162718334Speter
162818334Speter/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
162918334Speter   If X is 0, return -1.
163018334Speter
163118334Speter   This should be used via the floor_log2 macro.  */
163218334Speter
163318334Speterint
163418334Speterfloor_log2_wide (x)
163590282Sobrien     unsigned HOST_WIDE_INT x;
163618334Speter{
163790282Sobrien  int log = -1;
163818334Speter  while (x != 0)
163918334Speter    log++,
164018334Speter    x >>= 1;
164118334Speter  return log;
164218334Speter}
164318334Speter
164450615Sobrienstatic int float_handler_set;
164518334Speterint float_handled;
164618334Speterjmp_buf float_handler;
164718334Speter
164850615Sobrien/* Signals actually come here.  */
164950615Sobrien
165050615Sobrienstatic void
165150615Sobrienfloat_signal (signo)
165250615Sobrien     /* If this is missing, some compilers complain.  */
165350615Sobrien     int signo ATTRIBUTE_UNUSED;
165450615Sobrien{
165550615Sobrien  if (float_handled == 0)
165690282Sobrien    crash_signal (signo);
165750615Sobrien  float_handled = 0;
165890282Sobrien
165990282Sobrien  /* On System-V derived systems, we must reinstall the signal handler.
166090282Sobrien     This is harmless on BSD-derived systems.  */
166150615Sobrien  signal (SIGFPE, float_signal);
166250615Sobrien  longjmp (float_handler, 1);
166350615Sobrien}
166450615Sobrien
166518334Speter/* Specify where to longjmp to when a floating arithmetic error happens.
166618334Speter   If HANDLER is 0, it means don't handle the errors any more.  */
166718334Speter
166890282Sobrienstatic void
166918334Speterset_float_handler (handler)
167018334Speter     jmp_buf handler;
167118334Speter{
167218334Speter  float_handled = (handler != 0);
167318334Speter  if (handler)
167490282Sobrien    memcpy (float_handler, handler, sizeof (float_handler));
167550615Sobrien
167650615Sobrien  if (float_handled && ! float_handler_set)
167750615Sobrien    {
167850615Sobrien      signal (SIGFPE, float_signal);
167950615Sobrien      float_handler_set = 1;
168050615Sobrien    }
168118334Speter}
168218334Speter
168352558Sobrien/* This is a wrapper function for code which might elicit an
168452558Sobrien   arithmetic exception.  That code should be passed in as a function
168552558Sobrien   pointer FN, and one argument DATA.  DATA is usually a struct which
168652558Sobrien   contains the real input and output for function FN.  This function
168752558Sobrien   returns 0 (failure) if longjmp was called (i.e. an exception
168890282Sobrien   occurred.)  It returns 1 (success) otherwise.  */
168952558Sobrien
169052558Sobrienint
169152558Sobriendo_float_handler (fn, data)
169290282Sobrien     void (*fn) PARAMS ((PTR));
169390282Sobrien     PTR data;
169452558Sobrien{
169552558Sobrien  jmp_buf buf;
169652558Sobrien
169752558Sobrien  if (setjmp (buf))
169852558Sobrien    {
169990282Sobrien      /* We got here via longjmp () caused by an exception in function
170090282Sobrien         fn ().  */
170152558Sobrien      set_float_handler (NULL);
170252558Sobrien      return 0;
170352558Sobrien    }
170452558Sobrien
170552558Sobrien  set_float_handler (buf);
170652558Sobrien  (*fn)(data);
170752558Sobrien  set_float_handler (NULL);
170852558Sobrien  return 1;
170952558Sobrien}
171052558Sobrien
171190282Sobrien/* Handler for fatal signals, such as SIGSEGV.  These are transformed
171290282Sobrien   into ICE messages, which is much more user friendly.  */
171318334Speter
171418334Speterstatic void
171590282Sobriencrash_signal (signo)
171690282Sobrien     int signo;
171718334Speter{
171890282Sobrien  internal_error ("internal error: %s", strsignal (signo));
171918334Speter}
172018334Speter
172118334Speter/* Strip off a legitimate source ending from the input string NAME of
172218334Speter   length LEN.  Rather than having to know the names used by all of
172350615Sobrien   our front ends, we strip off an ending of a period followed by
172490282Sobrien   up to five characters.  (Java uses ".class".)  */
172518334Speter
172618334Spetervoid
172718334Speterstrip_off_ending (name, len)
172818334Speter     char *name;
172918334Speter     int len;
173018334Speter{
173150615Sobrien  int i;
173250615Sobrien  for (i = 2;  i < 6 && len > i;  i++)
173350615Sobrien    {
173450615Sobrien      if (name[len - i] == '.')
173550615Sobrien	{
173650615Sobrien	  name[len - i] = '\0';
173750615Sobrien	  break;
173850615Sobrien	}
173950615Sobrien    }
174018334Speter}
174118334Speter
174218334Speter/* Output a quoted string.  */
174350615Sobrien
174418334Spetervoid
174518334Speteroutput_quoted_string (asm_file, string)
174618334Speter     FILE *asm_file;
174752558Sobrien     const char *string;
174818334Speter{
174950615Sobrien#ifdef OUTPUT_QUOTED_STRING
175050615Sobrien  OUTPUT_QUOTED_STRING (asm_file, string);
175150615Sobrien#else
175218334Speter  char c;
175318334Speter
175418334Speter  putc ('\"', asm_file);
175518334Speter  while ((c = *string++) != 0)
175618334Speter    {
175796289Sobrien      if (ISPRINT (c))
175896289Sobrien	{
175996289Sobrien	  if (c == '\"' || c == '\\')
176096289Sobrien	    putc ('\\', asm_file);
176196289Sobrien	  putc (c, asm_file);
176296289Sobrien	}
176396289Sobrien      else
176496289Sobrien	fprintf (asm_file, "\\%03o", c);
176518334Speter    }
176618334Speter  putc ('\"', asm_file);
176750615Sobrien#endif
176818334Speter}
176918334Speter
177018334Speter/* Output a file name in the form wanted by System V.  */
177118334Speter
177218334Spetervoid
177318334Speteroutput_file_directive (asm_file, input_name)
177418334Speter     FILE *asm_file;
177552558Sobrien     const char *input_name;
177618334Speter{
177718334Speter  int len = strlen (input_name);
177852558Sobrien  const char *na = input_name + len;
177918334Speter
178018334Speter  /* NA gets INPUT_NAME sans directory names.  */
178118334Speter  while (na > input_name)
178218334Speter    {
178390282Sobrien      if (IS_DIR_SEPARATOR (na[-1]))
178490282Sobrien        break;
178518334Speter      na--;
178618334Speter    }
178718334Speter
178818334Speter#ifdef ASM_OUTPUT_MAIN_SOURCE_FILENAME
178918334Speter  ASM_OUTPUT_MAIN_SOURCE_FILENAME (asm_file, na);
179018334Speter#else
179118334Speter#ifdef ASM_OUTPUT_SOURCE_FILENAME
179218334Speter  ASM_OUTPUT_SOURCE_FILENAME (asm_file, na);
179318334Speter#else
179418334Speter  fprintf (asm_file, "\t.file\t");
179518334Speter  output_quoted_string (asm_file, na);
179618334Speter  fputc ('\n', asm_file);
179718334Speter#endif
179818334Speter#endif
179918334Speter}
180018334Speter
180190282Sobrien/* Routine to open a dump file.  Return true if the dump file is enabled.  */
180218334Speter
180390282Sobrienstatic int
180490282Sobrienopen_dump_file (index, decl)
180590282Sobrien     enum dump_file_index index;
180690282Sobrien     tree decl;
180718334Speter{
180890282Sobrien  char *dump_name;
180990282Sobrien  const char *open_arg;
181090282Sobrien  char seq[16];
181118334Speter
181290282Sobrien  if (! dump_file[index].enabled)
181390282Sobrien    return 0;
181450615Sobrien
181590282Sobrien  timevar_push (TV_DUMP);
181690282Sobrien  if (rtl_dump_file != NULL)
181790282Sobrien    fclose (rtl_dump_file);
181850615Sobrien
181990282Sobrien  sprintf (seq, DUMPFILE_FORMAT, index);
182050615Sobrien
182190282Sobrien  if (! dump_file[index].initialized)
182290282Sobrien    {
182390282Sobrien      /* If we've not initialized the files, do so now.  */
182490282Sobrien      if (graph_dump_format != no_graph
182590282Sobrien	  && dump_file[index].graph_dump_p)
182690282Sobrien	{
182790282Sobrien	  dump_name = concat (seq, dump_file[index].extension, NULL);
182890282Sobrien	  clean_graph_dump_file (dump_base_name, dump_name);
182990282Sobrien	  free (dump_name);
183090282Sobrien	}
183190282Sobrien      dump_file[index].initialized = 1;
183290282Sobrien      open_arg = "w";
183390282Sobrien    }
183490282Sobrien  else
183590282Sobrien    open_arg = "a";
183650615Sobrien
183790282Sobrien  dump_name = concat (dump_base_name, seq,
183890282Sobrien		      dump_file[index].extension, NULL);
183950615Sobrien
184090282Sobrien  rtl_dump_file = fopen (dump_name, open_arg);
184190282Sobrien  if (rtl_dump_file == NULL)
184290282Sobrien    fatal_io_error ("can't open %s", dump_name);
184390282Sobrien
184490282Sobrien  free (dump_name);
184590282Sobrien
184690282Sobrien  if (decl)
184790282Sobrien    fprintf (rtl_dump_file, "\n;; Function %s\n\n",
184890282Sobrien	     decl_printable_name (decl, 2));
184990282Sobrien
185090282Sobrien  timevar_pop (TV_DUMP);
185190282Sobrien  return 1;
185250615Sobrien}
185350615Sobrien
185490282Sobrien/* Routine to close a dump file.  */
185590282Sobrien
185650615Sobrienstatic void
185790282Sobrienclose_dump_file (index, func, insns)
185890282Sobrien     enum dump_file_index index;
185990282Sobrien     void (*func) PARAMS ((FILE *, rtx));
186090282Sobrien     rtx insns;
186150615Sobrien{
186290282Sobrien  if (! rtl_dump_file)
186390282Sobrien    return;
186450615Sobrien
186590282Sobrien  timevar_push (TV_DUMP);
186690282Sobrien  if (insns
186790282Sobrien      && graph_dump_format != no_graph
186890282Sobrien      && dump_file[index].graph_dump_p)
186990282Sobrien    {
187090282Sobrien      char seq[16];
187190282Sobrien      char *suffix;
187250615Sobrien
187390282Sobrien      sprintf (seq, DUMPFILE_FORMAT, index);
187490282Sobrien      suffix = concat (seq, dump_file[index].extension, NULL);
187590282Sobrien      print_rtl_graph_with_bb (dump_base_name, suffix, insns);
187690282Sobrien      free (suffix);
187790282Sobrien    }
187850615Sobrien
187990282Sobrien  if (func && insns)
188090282Sobrien    func (rtl_dump_file, insns);
188150615Sobrien
188290282Sobrien  fflush (rtl_dump_file);
188390282Sobrien  fclose (rtl_dump_file);
188450615Sobrien
188550615Sobrien  rtl_dump_file = NULL;
188690282Sobrien  timevar_pop (TV_DUMP);
188718334Speter}
188818334Speter
188952558Sobrien/* Do any final processing required for the declarations in VEC, of
189052558Sobrien   which there are LEN.  We write out inline functions and variables
189152558Sobrien   that have been deferred until this point, but which are required.
189290282Sobrien   Returns non-zero if anything was put out.  */
189390282Sobrien
189452558Sobrienint
189552558Sobrienwrapup_global_declarations (vec, len)
189652558Sobrien     tree *vec;
189752558Sobrien     int len;
189852558Sobrien{
189952558Sobrien  tree decl;
190052558Sobrien  int i;
190152558Sobrien  int reconsider;
190252558Sobrien  int output_something = 0;
190350615Sobrien
190452558Sobrien  for (i = 0; i < len; i++)
190552558Sobrien    {
190652558Sobrien      decl = vec[i];
190790282Sobrien
190852558Sobrien      /* We're not deferring this any longer.  */
190952558Sobrien      DECL_DEFER_OUTPUT (decl) = 0;
191090282Sobrien
191152558Sobrien      if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0
191252558Sobrien	  && incomplete_decl_finalize_hook != 0)
191352558Sobrien	(*incomplete_decl_finalize_hook) (decl);
191452558Sobrien    }
191552558Sobrien
191652558Sobrien  /* Now emit any global variables or functions that we have been
191752558Sobrien     putting off.  We need to loop in case one of the things emitted
191852558Sobrien     here references another one which comes earlier in the list.  */
191952558Sobrien  do
192052558Sobrien    {
192152558Sobrien      reconsider = 0;
192252558Sobrien      for (i = 0; i < len; i++)
192352558Sobrien	{
192452558Sobrien	  decl = vec[i];
192552558Sobrien
192652558Sobrien	  if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl))
192752558Sobrien	    continue;
192852558Sobrien
192952558Sobrien	  /* Don't write out static consts, unless we still need them.
193052558Sobrien
193152558Sobrien	     We also keep static consts if not optimizing (for debugging),
193252558Sobrien	     unless the user specified -fno-keep-static-consts.
193352558Sobrien	     ??? They might be better written into the debug information.
193452558Sobrien	     This is possible when using DWARF.
193552558Sobrien
193652558Sobrien	     A language processor that wants static constants to be always
193752558Sobrien	     written out (even if it is not used) is responsible for
193852558Sobrien	     calling rest_of_decl_compilation itself.  E.g. the C front-end
193952558Sobrien	     calls rest_of_decl_compilation from finish_decl.
194052558Sobrien	     One motivation for this is that is conventional in some
194152558Sobrien	     environments to write things like:
194252558Sobrien	     static const char rcsid[] = "... version string ...";
194352558Sobrien	     intending to force the string to be in the executable.
194452558Sobrien
194552558Sobrien	     A language processor that would prefer to have unneeded
194652558Sobrien	     static constants "optimized away" would just defer writing
194752558Sobrien	     them out until here.  E.g. C++ does this, because static
194852558Sobrien	     constants are often defined in header files.
194952558Sobrien
195052558Sobrien	     ??? A tempting alternative (for both C and C++) would be
195152558Sobrien	     to force a constant to be written if and only if it is
195252558Sobrien	     defined in a main file, as opposed to an include file.  */
195352558Sobrien
195496289Sobrien	  if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
195552558Sobrien	    {
195696289Sobrien	      bool needed = 1;
195796289Sobrien
195896289Sobrien	      if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
195996289Sobrien		/* needed */;
196096289Sobrien	      else if (DECL_COMDAT (decl))
196196289Sobrien		needed = 0;
196296289Sobrien	      else if (TREE_READONLY (decl) && !TREE_PUBLIC (decl)
196396289Sobrien		       && (optimize || !flag_keep_static_consts
196496289Sobrien			   || DECL_ARTIFICIAL (decl)))
196596289Sobrien		needed = 0;
196696289Sobrien
196796289Sobrien	      if (needed)
196896289Sobrien		{
196996289Sobrien		  reconsider = 1;
197096289Sobrien		  rest_of_decl_compilation (decl, NULL, 1, 1);
197196289Sobrien		}
197252558Sobrien	    }
197352558Sobrien
197452558Sobrien	  if (TREE_CODE (decl) == FUNCTION_DECL
197552558Sobrien	      && DECL_INITIAL (decl) != 0
197652558Sobrien	      && DECL_SAVED_INSNS (decl) != 0
197752558Sobrien	      && (flag_keep_inline_functions
197852558Sobrien		  || (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
197952558Sobrien		  || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
198052558Sobrien	    {
198152558Sobrien	      reconsider = 1;
198252558Sobrien	      output_inline_function (decl);
198352558Sobrien	    }
198452558Sobrien	}
198552558Sobrien
198652558Sobrien      if (reconsider)
198752558Sobrien	output_something = 1;
198852558Sobrien    }
198952558Sobrien  while (reconsider);
199052558Sobrien
199152558Sobrien  return output_something;
199252558Sobrien}
199352558Sobrien
199452558Sobrien/* Issue appropriate warnings for the global declarations in VEC (of
199552558Sobrien   which there are LEN).  Output debugging information for them.  */
199690282Sobrien
199752558Sobrienvoid
199852558Sobriencheck_global_declarations (vec, len)
199952558Sobrien     tree *vec;
200052558Sobrien     int len;
200152558Sobrien{
200252558Sobrien  tree decl;
200352558Sobrien  int i;
200452558Sobrien
200552558Sobrien  for (i = 0; i < len; i++)
200652558Sobrien    {
200752558Sobrien      decl = vec[i];
200852558Sobrien
200952558Sobrien      if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)
201052558Sobrien	  && ! TREE_ASM_WRITTEN (decl))
201152558Sobrien	/* Cancel the RTL for this decl so that, if debugging info
201252558Sobrien	   output for global variables is still to come,
201352558Sobrien	   this one will be omitted.  */
201490282Sobrien	SET_DECL_RTL (decl, NULL_RTX);
201552558Sobrien
201652558Sobrien      /* Warn about any function
201752558Sobrien	 declared static but not defined.
201852558Sobrien	 We don't warn about variables,
201952558Sobrien	 because many programs have static variables
202052558Sobrien	 that exist only to get some text into the object file.  */
202152558Sobrien      if (TREE_CODE (decl) == FUNCTION_DECL
202290282Sobrien	  && (warn_unused_function
202352558Sobrien	      || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
202452558Sobrien	  && DECL_INITIAL (decl) == 0
202552558Sobrien	  && DECL_EXTERNAL (decl)
202652558Sobrien	  && ! DECL_ARTIFICIAL (decl)
202752558Sobrien	  && ! TREE_PUBLIC (decl))
202852558Sobrien	{
202952558Sobrien	  if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
203052558Sobrien	    pedwarn_with_decl (decl,
203152558Sobrien			       "`%s' used but never defined");
203252558Sobrien	  else
203352558Sobrien	    warning_with_decl (decl,
203452558Sobrien			       "`%s' declared `static' but never defined");
203552558Sobrien	  /* This symbol is effectively an "extern" declaration now.  */
203652558Sobrien	  TREE_PUBLIC (decl) = 1;
203752558Sobrien	  assemble_external (decl);
203852558Sobrien	}
203952558Sobrien
204052558Sobrien      /* Warn about static fns or vars defined but not used,
204152558Sobrien	 but not about inline functions or static consts
204252558Sobrien	 since defining those in header files is normal practice.  */
204390282Sobrien      if (((warn_unused_function
204490282Sobrien	    && TREE_CODE (decl) == FUNCTION_DECL && ! DECL_INLINE (decl))
204590282Sobrien	   || (warn_unused_variable
204690282Sobrien	       && TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
204752558Sobrien	  && ! DECL_IN_SYSTEM_HEADER (decl)
204852558Sobrien	  && ! DECL_EXTERNAL (decl)
204952558Sobrien	  && ! TREE_PUBLIC (decl)
205052558Sobrien	  && ! TREE_USED (decl)
205152558Sobrien	  && (TREE_CODE (decl) == FUNCTION_DECL || ! DECL_REGISTER (decl))
205252558Sobrien	  /* The TREE_USED bit for file-scope decls
205352558Sobrien	     is kept in the identifier, to handle multiple
205452558Sobrien	     external decls in different scopes.  */
205552558Sobrien	  && ! TREE_USED (DECL_NAME (decl)))
205652558Sobrien	warning_with_decl (decl, "`%s' defined but not used");
205752558Sobrien
205890282Sobrien      timevar_push (TV_SYMOUT);
205990282Sobrien      (*debug_hooks->global_decl) (decl);
206090282Sobrien      timevar_pop (TV_SYMOUT);
206152558Sobrien    }
206252558Sobrien}
206352558Sobrien
206490282Sobrien/* Save the current INPUT_FILENAME and LINENO on the top entry in the
206590282Sobrien   INPUT_FILE_STACK.  Push a new entry for FILE and LINE, and set the
206690282Sobrien   INPUT_FILENAME and LINENO accordingly.  */
206718334Speter
206890282Sobrienvoid
206990282Sobrienpush_srcloc (file, line)
207090282Sobrien     const char *file;
207190282Sobrien     int line;
207218334Speter{
207390282Sobrien  struct file_stack *fs;
207418334Speter
207590282Sobrien  if (input_file_stack)
207618334Speter    {
207790282Sobrien      input_file_stack->name = input_filename;
207890282Sobrien      input_file_stack->line = lineno;
207918334Speter    }
208018334Speter
208190282Sobrien  fs = (struct file_stack *) xmalloc (sizeof (struct file_stack));
208290282Sobrien  fs->name = input_filename = file;
208390282Sobrien  fs->line = lineno = line;
208490282Sobrien  fs->indent_level = 0;
208590282Sobrien  fs->next = input_file_stack;
208690282Sobrien  input_file_stack = fs;
208790282Sobrien  input_file_stack_tick++;
208890282Sobrien}
208918334Speter
209090282Sobrien/* Pop the top entry off the stack of presently open source files.
209190282Sobrien   Restore the INPUT_FILENAME and LINENO from the new topmost entry on
209290282Sobrien   the stack.  */
209318334Speter
209490282Sobrienvoid
209590282Sobrienpop_srcloc ()
209690282Sobrien{
209790282Sobrien  struct file_stack *fs;
209818334Speter
209990282Sobrien  fs = input_file_stack;
210090282Sobrien  input_file_stack = fs->next;
210190282Sobrien  free (fs);
210290282Sobrien  input_file_stack_tick++;
210390282Sobrien  /* The initial source file is never popped.  */
210490282Sobrien  if (!input_file_stack)
210590282Sobrien    abort ();
210690282Sobrien  input_filename = input_file_stack->name;
210790282Sobrien  lineno = input_file_stack->line;
210890282Sobrien}
210918334Speter
211090282Sobrien/* Compile an entire translation unit.  Write a file of assembly
211190282Sobrien   output and various debugging dumps.  */
211218334Speter
211390282Sobrienstatic void
211490282Sobriencompile_file ()
211590282Sobrien{
211690282Sobrien  tree globals;
211718334Speter
211818334Speter  /* Initialize yet another pass.  */
211918334Speter
212050615Sobrien  init_final (main_input_filename);
212150615Sobrien  init_branch_prob (dump_base_name);
212218334Speter
212390282Sobrien  timevar_push (TV_PARSE);
212418334Speter
212518334Speter  /* Call the parser, which parses the entire file
212618334Speter     (calling rest_of_compilation for each function).  */
212790282Sobrien  yyparse ();
212818334Speter
212990282Sobrien  /* In case there were missing block closers,
213090282Sobrien     get us back to the global binding level.  */
213190282Sobrien  (*lang_hooks.clear_binding_stack) ();
213218334Speter
213318334Speter  /* Compilation is now finished except for writing
213418334Speter     what's left of the symbol table output.  */
213518334Speter
213690282Sobrien  timevar_pop (TV_PARSE);
213718334Speter
213852558Sobrien  if (flag_syntax_only)
213990282Sobrien    return;
214052558Sobrien
214118334Speter  globals = getdecls ();
214218334Speter
214318334Speter  /* Really define vars that have had only a tentative definition.
214418334Speter     Really output inline functions that must actually be callable
214518334Speter     and have not been output so far.  */
214618334Speter
214718334Speter  {
214818334Speter    int len = list_length (globals);
214990282Sobrien    tree *vec = (tree *) xmalloc (sizeof (tree) * len);
215018334Speter    int i;
215118334Speter    tree decl;
215218334Speter
215318334Speter    /* Process the decls in reverse order--earliest first.
215418334Speter       Put them into VEC from back to front, then take out from front.  */
215518334Speter
215618334Speter    for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
215718334Speter      vec[len - i - 1] = decl;
215818334Speter
215952558Sobrien    wrapup_global_declarations (vec, len);
216018334Speter
216152558Sobrien    /* This must occur after the loop to output deferred functions.  Else
216252558Sobrien       the profiler initializer would not be emitted if all the functions
216352558Sobrien       in this compilation unit were deferred.
216418334Speter
216552558Sobrien       output_func_start_profiler can not cause any additional functions or
216652558Sobrien       data to need to be output, so it need not be in the deferred function
216752558Sobrien       loop above.  */
216852558Sobrien    output_func_start_profiler ();
216918334Speter
217090282Sobrien    check_global_declarations (vec, len);
217150615Sobrien
217290282Sobrien    /* Clean up.  */
217390282Sobrien    free (vec);
217418334Speter  }
217518334Speter
217618334Speter  /* Write out any pending weak symbol declarations.  */
217718334Speter
217818334Speter  weak_finish ();
217918334Speter
218090282Sobrien  /* Do dbx symbols.  */
218190282Sobrien  timevar_push (TV_SYMOUT);
218218334Speter
218350615Sobrien#ifdef DWARF2_UNWIND_INFO
218450615Sobrien  if (dwarf2out_do_frame ())
218550615Sobrien    dwarf2out_frame_finish ();
218650615Sobrien#endif
218750615Sobrien
218890282Sobrien  (*debug_hooks->finish) (main_input_filename);
218990282Sobrien  timevar_pop (TV_SYMOUT);
219050615Sobrien
219118334Speter  /* Output some stuff at end of file if nec.  */
219218334Speter
219390282Sobrien  dw2_output_indirect_constants ();
219490282Sobrien
219550615Sobrien  end_final (dump_base_name);
219618334Speter
219790282Sobrien  if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
219890282Sobrien    {
219990282Sobrien      timevar_push (TV_DUMP);
220090282Sobrien      open_dump_file (DFI_bp, NULL);
220152558Sobrien
220290282Sobrien      end_branch_prob ();
220318334Speter
220490282Sobrien      close_dump_file (DFI_bp, NULL, NULL_RTX);
220590282Sobrien      timevar_pop (TV_DUMP);
220618334Speter    }
220718334Speter
220890282Sobrien#ifdef ASM_FILE_END
220990282Sobrien  ASM_FILE_END (asm_out_file);
221090282Sobrien#endif
221118334Speter
221290282Sobrien  /* Attach a special .ident directive to the end of the file to identify
221390282Sobrien     the version of GCC which compiled this code.  The format of the .ident
221490282Sobrien     string is patterned after the ones produced by native SVR4 compilers.  */
221590282Sobrien#ifdef IDENT_ASM_OP
221690282Sobrien  if (!flag_no_ident)
221790282Sobrien    fprintf (asm_out_file, "%s\"GCC: (GNU) %s\"\n",
221890282Sobrien	     IDENT_ASM_OP, version_string);
221952558Sobrien#endif
222052558Sobrien
222190282Sobrien  if (optimize > 0 && open_dump_file (DFI_combine, NULL))
222218334Speter    {
222390282Sobrien      timevar_push (TV_DUMP);
222490282Sobrien      dump_combine_total_stats (rtl_dump_file);
222590282Sobrien      close_dump_file (DFI_combine, NULL, NULL_RTX);
222690282Sobrien      timevar_pop (TV_DUMP);
222718334Speter    }
222818334Speter}
222918334Speter
223018334Speter/* This is called from various places for FUNCTION_DECL, VAR_DECL,
223118334Speter   and TYPE_DECL nodes.
223218334Speter
223390282Sobrien   This does nothing for local (non-static) variables, unless the
223490282Sobrien   variable is a register variable with an ASMSPEC.  In that case, or
223590282Sobrien   if the variable is not an automatic, it sets up the RTL and
223690282Sobrien   outputs any assembler code (label definition, storage allocation
223790282Sobrien   and initialization).
223818334Speter
223918334Speter   DECL is the declaration.  If ASMSPEC is nonzero, it specifies
224018334Speter   the assembler symbol name to be used.  TOP_LEVEL is nonzero
224118334Speter   if this declaration is not within a function.  */
224218334Speter
224318334Spetervoid
224418334Speterrest_of_decl_compilation (decl, asmspec, top_level, at_end)
224518334Speter     tree decl;
224652558Sobrien     const char *asmspec;
224718334Speter     int top_level;
224818334Speter     int at_end;
224918334Speter{
225018334Speter  /* Declarations of variables, and of functions defined elsewhere.  */
225118334Speter
225218334Speter/* The most obvious approach, to put an #ifndef around where
225318334Speter   this macro is used, doesn't work since it's inside a macro call.  */
225418334Speter#ifndef ASM_FINISH_DECLARE_OBJECT
225518334Speter#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP, END)
225618334Speter#endif
225718334Speter
225818334Speter  /* Forward declarations for nested functions are not "external",
225918334Speter     but we need to treat them as if they were.  */
226018334Speter  if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
226118334Speter      || TREE_CODE (decl) == FUNCTION_DECL)
226290282Sobrien    {
226390282Sobrien      timevar_push (TV_VARCONST);
226490282Sobrien      if (asmspec)
226590282Sobrien	make_decl_rtl (decl, asmspec);
226690282Sobrien      /* Don't output anything
226790282Sobrien	 when a tentative file-scope definition is seen.
226890282Sobrien	 But at end of compilation, do output code for them.  */
226990282Sobrien      if (at_end || !DECL_DEFER_OUTPUT (decl))
227090282Sobrien	assemble_variable (decl, top_level, at_end, 0);
227190282Sobrien      if (decl == last_assemble_variable_decl)
227290282Sobrien	{
227390282Sobrien	  ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
227490282Sobrien				     top_level, at_end);
227590282Sobrien	}
227690282Sobrien      timevar_pop (TV_VARCONST);
227790282Sobrien    }
227818334Speter  else if (DECL_REGISTER (decl) && asmspec != 0)
227918334Speter    {
228018334Speter      if (decode_reg_name (asmspec) >= 0)
228118334Speter	{
228290282Sobrien	  SET_DECL_RTL (decl, NULL_RTX);
228390282Sobrien	  make_decl_rtl (decl, asmspec);
228418334Speter	}
228518334Speter      else
228690282Sobrien	{
228790282Sobrien	  error ("invalid register name `%s' for register variable", asmspec);
228890282Sobrien	  DECL_REGISTER (decl) = 0;
228990282Sobrien	  if (!top_level)
229090282Sobrien	    expand_decl (decl);
229190282Sobrien	}
229218334Speter    }
229318334Speter#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
229418334Speter  else if ((write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
229518334Speter	   && TREE_CODE (decl) == TYPE_DECL)
229690282Sobrien    {
229790282Sobrien      timevar_push (TV_SYMOUT);
229890282Sobrien      dbxout_symbol (decl, 0);
229990282Sobrien      timevar_pop (TV_SYMOUT);
230090282Sobrien    }
230118334Speter#endif
230218334Speter#ifdef SDB_DEBUGGING_INFO
230318334Speter  else if (write_symbols == SDB_DEBUG && top_level
230418334Speter	   && TREE_CODE (decl) == TYPE_DECL)
230590282Sobrien    {
230690282Sobrien      timevar_push (TV_SYMOUT);
230790282Sobrien      sdbout_symbol (decl, 0);
230890282Sobrien      timevar_pop (TV_SYMOUT);
230990282Sobrien    }
231018334Speter#endif
231118334Speter}
231218334Speter
231318334Speter/* Called after finishing a record, union or enumeral type.  */
231418334Speter
231518334Spetervoid
231618334Speterrest_of_type_compilation (type, toplev)
231752558Sobrien#if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO) || defined (SDB_DEBUGGING_INFO)
231818334Speter     tree type;
231918334Speter     int toplev;
232052558Sobrien#else
232152558Sobrien     tree type ATTRIBUTE_UNUSED;
232252558Sobrien     int toplev ATTRIBUTE_UNUSED;
232352558Sobrien#endif
232418334Speter{
232590282Sobrien  timevar_push (TV_SYMOUT);
232618334Speter#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
232718334Speter  if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
232890282Sobrien    dbxout_symbol (TYPE_STUB_DECL (type), !toplev);
232918334Speter#endif
233018334Speter#ifdef SDB_DEBUGGING_INFO
233118334Speter  if (write_symbols == SDB_DEBUG)
233290282Sobrien    sdbout_symbol (TYPE_STUB_DECL (type), !toplev);
233318334Speter#endif
233490282Sobrien#ifdef DWARF2_DEBUGGING_INFO
233590282Sobrien  if ((write_symbols == DWARF2_DEBUG
233690282Sobrien       || write_symbols == VMS_AND_DWARF2_DEBUG)
233790282Sobrien      && toplev)
233890282Sobrien    dwarf2out_decl (TYPE_STUB_DECL (type));
233990282Sobrien#endif
234090282Sobrien  timevar_pop (TV_SYMOUT);
234118334Speter}
234218334Speter
234318334Speter/* This is called from finish_function (within yyparse)
234418334Speter   after each top-level definition is parsed.
234518334Speter   It is supposed to compile that function or variable
234618334Speter   and output the assembler code for it.
234718334Speter   After we return, the tree storage is freed.  */
234818334Speter
234918334Spetervoid
235018334Speterrest_of_compilation (decl)
235118334Speter     tree decl;
235218334Speter{
235390282Sobrien  rtx insns;
235418334Speter  int tem;
235518334Speter  int failure = 0;
235652558Sobrien  int rebuild_label_notes_after_reload;
235790282Sobrien  int register_life_up_to_date;
235896289Sobrien  int cleanup_crossjump;
235918334Speter
236090282Sobrien  timevar_push (TV_REST_OF_COMPILATION);
236190282Sobrien
236290282Sobrien  /* Now that we're out of the frontend, we shouldn't have any more
236390282Sobrien     CONCATs anywhere.  */
236490282Sobrien  generating_concat_p = 0;
236590282Sobrien
236690282Sobrien  /* When processing delayed functions, prepare_function_start() won't
236790282Sobrien     have been run to re-initialize it.  */
236890282Sobrien  cse_not_expected = ! optimize;
236990282Sobrien
237090282Sobrien  /* First, make sure that NOTE_BLOCK is set correctly for each
237190282Sobrien     NOTE_INSN_BLOCK_BEG/NOTE_INSN_BLOCK_END note.  */
237290282Sobrien  if (!cfun->x_whole_function_mode_p)
237390282Sobrien    identify_blocks ();
237490282Sobrien
237590282Sobrien  /* In function-at-a-time mode, we do not attempt to keep the BLOCK
237690282Sobrien     tree in sensible shape.  So, we just recalculate it here.  */
237790282Sobrien  if (cfun->x_whole_function_mode_p)
237890282Sobrien    reorder_blocks ();
237990282Sobrien
238090282Sobrien  init_flow ();
238190282Sobrien
238218334Speter  /* If we are reconsidering an inline function
238318334Speter     at the end of compilation, skip the stuff for making it inline.  */
238418334Speter
238518334Speter  if (DECL_SAVED_INSNS (decl) == 0)
238618334Speter    {
238750615Sobrien      int inlinable = 0;
238890282Sobrien      tree parent;
238952558Sobrien      const char *lose;
239018334Speter
239190282Sobrien      /* If this is nested inside an inlined external function, pretend
239290282Sobrien	 it was only declared.  Since we cannot inline such functions,
239390282Sobrien	 generating code for this one is not only not necessary but will
239490282Sobrien	 confuse some debugging output writers.  */
239590282Sobrien      for (parent = DECL_CONTEXT (current_function_decl);
239690282Sobrien	   parent != NULL_TREE;
239790282Sobrien	   parent = get_containing_scope (parent))
239890282Sobrien	if (TREE_CODE (parent) == FUNCTION_DECL
239990282Sobrien	    && DECL_INLINE (parent) && DECL_EXTERNAL (parent))
240090282Sobrien	  {
240190282Sobrien	    DECL_INITIAL (decl) = 0;
240290282Sobrien	    goto exit_rest_of_compilation;
240390282Sobrien	  }
240490282Sobrien
240518334Speter      /* If requested, consider whether to make this function inline.  */
240690282Sobrien      if ((DECL_INLINE (decl) && !flag_no_inline)
240790282Sobrien	  || flag_inline_functions)
240890282Sobrien	{
240990282Sobrien	  timevar_push (TV_INTEGRATION);
241090282Sobrien	  lose = function_cannot_inline_p (decl);
241190282Sobrien	  timevar_pop (TV_INTEGRATION);
241290282Sobrien	  if (lose || ! optimize)
241390282Sobrien	    {
241490282Sobrien	      if (warn_inline && DECL_INLINE (decl))
241590282Sobrien		warning_with_decl (decl, lose);
241690282Sobrien	      DECL_ABSTRACT_ORIGIN (decl) = 0;
241790282Sobrien	      /* Don't really compile an extern inline function.
241890282Sobrien		 If we can't make it inline, pretend
241990282Sobrien		 it was only declared.  */
242090282Sobrien	      if (DECL_EXTERNAL (decl))
242190282Sobrien		{
242290282Sobrien		  DECL_INITIAL (decl) = 0;
242390282Sobrien		  goto exit_rest_of_compilation;
242490282Sobrien		}
242590282Sobrien	    }
242690282Sobrien	  else
242790282Sobrien	    /* ??? Note that this has the effect of making it look
242890282Sobrien		 like "inline" was specified for a function if we choose
242990282Sobrien		 to inline it.  This isn't quite right, but it's
243090282Sobrien		 probably not worth the trouble to fix.  */
243190282Sobrien	    inlinable = DECL_INLINE (decl) = 1;
243290282Sobrien	}
243318334Speter
243418334Speter      insns = get_insns ();
243518334Speter
243618334Speter      /* Dump the rtl code if we are dumping rtl.  */
243718334Speter
243890282Sobrien      if (open_dump_file (DFI_rtl, decl))
243950615Sobrien	{
244050615Sobrien	  if (DECL_SAVED_INSNS (decl))
244150615Sobrien	    fprintf (rtl_dump_file, ";; (integrable)\n\n");
244290282Sobrien	  close_dump_file (DFI_rtl, print_rtl, insns);
244350615Sobrien	}
244418334Speter
244590282Sobrien      /* Convert from NOTE_INSN_EH_REGION style notes, and do other
244690282Sobrien	 sorts of eh initialization.  Delay this until after the
244790282Sobrien         initial rtl dump so that we can see the original nesting.  */
244890282Sobrien      convert_from_eh_region_ranges ();
244950615Sobrien
245018334Speter      /* If function is inline, and we don't yet know whether to
245118334Speter	 compile it by itself, defer decision till end of compilation.
245218334Speter	 finish_compilation will call rest_of_compilation again
245318334Speter	 for those functions that need to be output.  Also defer those
245490282Sobrien	 functions that we are supposed to defer.  */
245518334Speter
245690282Sobrien      if (inlinable
245790282Sobrien	  || (DECL_INLINE (decl)
245890282Sobrien	      && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)
245996289Sobrien		   && ! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
246090282Sobrien		   && ! flag_keep_inline_functions)
246190282Sobrien		  || DECL_EXTERNAL (decl))))
246290282Sobrien	DECL_DEFER_OUTPUT (decl) = 1;
246350615Sobrien
246490282Sobrien      if (DECL_INLINE (decl))
246590282Sobrien	/* DWARF wants separate debugging info for abstract and
246690282Sobrien	   concrete instances of all inline functions, including those
246790282Sobrien	   declared inline but not inlined, and those inlined even
246890282Sobrien	   though they weren't declared inline.  Conveniently, that's
246990282Sobrien	   what DECL_INLINE means at this point.  */
247090282Sobrien	(*debug_hooks->deferred_inline_function) (decl);
247190282Sobrien
247290282Sobrien      if (DECL_DEFER_OUTPUT (decl))
247350615Sobrien	{
247490282Sobrien	  /* If -Wreturn-type, we have to do a bit of compilation.  We just
247590282Sobrien	     want to call cleanup the cfg to figure out whether or not we can
247690282Sobrien	     fall off the end of the function; we do the minimum amount of
247790282Sobrien	     work necessary to make that safe.  */
247850615Sobrien	  if (warn_return_type)
247918334Speter	    {
248050615Sobrien	      int saved_optimize = optimize;
248190282Sobrien
248250615Sobrien	      optimize = 0;
248390282Sobrien	      rebuild_jump_labels (insns);
248450615Sobrien	      find_exception_handler_labels ();
248590282Sobrien	      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
248690282Sobrien	      cleanup_cfg (CLEANUP_PRE_SIBCALL | CLEANUP_PRE_LOOP);
248750615Sobrien	      optimize = saved_optimize;
248890282Sobrien
248990282Sobrien	      /* CFG is no longer maintained up-to-date.  */
249090282Sobrien	      free_bb_for_insn ();
249150615Sobrien	    }
249250615Sobrien
249390282Sobrien	  current_function_nothrow = nothrow_function_p ();
249490282Sobrien	  if (current_function_nothrow)
249590282Sobrien	    /* Now we know that this can't throw; set the flag for the benefit
249690282Sobrien	       of other functions later in this translation unit.  */
249790282Sobrien	    TREE_NOTHROW (current_function_decl) = 1;
249890282Sobrien
249990282Sobrien	  timevar_push (TV_INTEGRATION);
250090282Sobrien	  save_for_inline (decl);
250190282Sobrien	  timevar_pop (TV_INTEGRATION);
250290282Sobrien	  DECL_SAVED_INSNS (decl)->inlinable = inlinable;
250350615Sobrien	  goto exit_rest_of_compilation;
250418334Speter	}
250518334Speter
250618334Speter      /* If specified extern inline but we aren't inlining it, we are
250752558Sobrien	 done.  This goes for anything that gets here with DECL_EXTERNAL
250852558Sobrien	 set, not just things with DECL_INLINE.  */
250952558Sobrien      if (DECL_EXTERNAL (decl))
251018334Speter	goto exit_rest_of_compilation;
251118334Speter    }
251218334Speter
251390282Sobrien  /* If we're emitting a nested function, make sure its parent gets
251490282Sobrien     emitted as well.  Doing otherwise confuses debug info.  */
251590282Sobrien  {
251690282Sobrien    tree parent;
251790282Sobrien    for (parent = DECL_CONTEXT (current_function_decl);
251890282Sobrien	 parent != NULL_TREE;
251990282Sobrien	 parent = get_containing_scope (parent))
252090282Sobrien      if (TREE_CODE (parent) == FUNCTION_DECL)
252190282Sobrien	TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (parent)) = 1;
252290282Sobrien  }
252390282Sobrien
252490282Sobrien  /* We are now committed to emitting code for this function.  Do any
252590282Sobrien     preparation, such as emitting abstract debug info for the inline
252690282Sobrien     before it gets mangled by optimization.  */
252790282Sobrien  if (DECL_INLINE (decl))
252890282Sobrien    (*debug_hooks->outlining_inline_function) (decl);
252990282Sobrien
253090282Sobrien  /* Remove any notes we don't need.  That will make iterating
253190282Sobrien     over the instruction sequence faster, and allow the garbage
253290282Sobrien     collector to reclaim the memory used by the notes.  */
253390282Sobrien  remove_unnecessary_notes ();
253490282Sobrien  reorder_blocks ();
253590282Sobrien
253690282Sobrien  ggc_collect ();
253790282Sobrien
253890282Sobrien  /* Initialize some variables used by the optimizers.  */
253990282Sobrien  init_function_for_compilation ();
254090282Sobrien
254118334Speter  if (! DECL_DEFER_OUTPUT (decl))
254218334Speter    TREE_ASM_WRITTEN (decl) = 1;
254318334Speter
254490282Sobrien  /* Now that integrate will no longer see our rtl, we need not
254590282Sobrien     distinguish between the return value of this function and the
254690282Sobrien     return value of called functions.  Also, we can remove all SETs
254790282Sobrien     of subregs of hard registers; they are only here because of
254890282Sobrien     integrate.  Also, we can now initialize pseudos intended to
254990282Sobrien     carry magic hard reg data throughout the function.  */
255018334Speter  rtx_equal_function_value_matters = 0;
255190282Sobrien  purge_hard_subreg_sets (get_insns ());
255218334Speter
255396289Sobrien  /* Early return if there were errors.  We can run afoul of our
255496289Sobrien     consistency checks, and there's not really much point in fixing them.
255596289Sobrien     Don't return yet if -Wreturn-type; we need to do cleanup_cfg.  */
255696289Sobrien  if (((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type)
255796289Sobrien      || errorcount || sorrycount)
255890282Sobrien    goto exit_rest_of_compilation;
255990282Sobrien
256090282Sobrien  /* We may have potential sibling or tail recursion sites.  Select one
256190282Sobrien     (of possibly multiple) methods of performing the call.  */
256290282Sobrien  if (flag_optimize_sibling_calls)
256318334Speter    {
256490282Sobrien      timevar_push (TV_JUMP);
256590282Sobrien      open_dump_file (DFI_sibling, decl);
256690282Sobrien
256790282Sobrien      optimize_sibling_and_tail_recursive_calls ();
256890282Sobrien
256990282Sobrien      close_dump_file (DFI_sibling, print_rtl, get_insns ());
257090282Sobrien      timevar_pop (TV_JUMP);
257118334Speter    }
257218334Speter
257390282Sobrien  /* Complete generation of exception handling code.  */
257490282Sobrien  find_exception_handler_labels ();
257590282Sobrien  if (doing_eh (0))
257690282Sobrien    {
257790282Sobrien      timevar_push (TV_JUMP);
257890282Sobrien      open_dump_file (DFI_eh, decl);
257918334Speter
258090282Sobrien      finish_eh_generation ();
258190282Sobrien
258290282Sobrien      close_dump_file (DFI_eh, print_rtl, get_insns ());
258390282Sobrien      timevar_pop (TV_JUMP);
258490282Sobrien    }
258590282Sobrien
258696289Sobrien  /* Delay emitting hard_reg_initial_value sets until after EH landing pad
258796289Sobrien     generation, which might create new sets.  */
258896289Sobrien  emit_initial_value_sets ();
258996289Sobrien
259018334Speter#ifdef FINALIZE_PIC
259118334Speter  /* If we are doing position-independent code generation, now
259218334Speter     is the time to output special prologues and epilogues.
259318334Speter     We do not want to do this earlier, because it just clutters
259418334Speter     up inline functions with meaningless insns.  */
259518334Speter  if (flag_pic)
259618334Speter    FINALIZE_PIC;
259718334Speter#endif
259818334Speter
259918334Speter  insns = get_insns ();
260018334Speter
260118334Speter  /* Copy any shared structure that should not be shared.  */
260272566Sobrien  unshare_all_rtl (current_function_decl, insns);
260318334Speter
260450615Sobrien#ifdef SETJMP_VIA_SAVE_AREA
260590282Sobrien  /* This must be performed before virtual register instantiation.  */
260650615Sobrien  if (current_function_calls_alloca)
260750615Sobrien    optimize_save_area_alloca (insns);
260850615Sobrien#endif
260950615Sobrien
261018334Speter  /* Instantiate all virtual registers.  */
261190282Sobrien  instantiate_virtual_regs (current_function_decl, insns);
261218334Speter
261390282Sobrien  open_dump_file (DFI_jump, decl);
261418334Speter
261550615Sobrien  /* Always do one jump optimization pass to ensure that JUMP_LABEL fields
261650615Sobrien     are initialized and to compute whether control can drop off the end
261750615Sobrien     of the function.  */
261818334Speter
261990282Sobrien  timevar_push (TV_JUMP);
262090282Sobrien  /* Turn NOTE_INSN_EXPECTED_VALUE into REG_BR_PROB.  Do this
262190282Sobrien     before jump optimization switches branch directions.  */
262290282Sobrien  expected_value_to_br_prob ();
262390282Sobrien
262490282Sobrien  reg_scan (insns, max_reg_num (), 0);
262590282Sobrien  rebuild_jump_labels (insns);
262690282Sobrien  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
262790282Sobrien  cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP);
262890282Sobrien
262990282Sobrien  /* CFG is no longer maintained up-to-date.  */
263090282Sobrien  free_bb_for_insn ();
263190282Sobrien  copy_loop_headers (insns);
263290282Sobrien  purge_line_number_notes (insns);
263390282Sobrien
263490282Sobrien  timevar_pop (TV_JUMP);
263590282Sobrien
263618334Speter  /* Now is when we stop if -fsyntax-only and -Wreturn-type.  */
263718334Speter  if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl))
263890282Sobrien    {
263990282Sobrien      close_dump_file (DFI_jump, print_rtl, insns);
264090282Sobrien      goto exit_rest_of_compilation;
264190282Sobrien    }
264218334Speter
264390282Sobrien  /* Long term, this should probably move before the jump optimizer too,
264490282Sobrien     but I didn't want to disturb the rtl_dump_and_exit and related
264590282Sobrien     stuff at this time.  */
264690282Sobrien  if (optimize > 0 && flag_ssa)
264790282Sobrien    {
264890282Sobrien      /* Convert to SSA form.  */
264918334Speter
265090282Sobrien      timevar_push (TV_TO_SSA);
265190282Sobrien      open_dump_file (DFI_ssa, decl);
265218334Speter
265390282Sobrien      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
265490282Sobrien      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
265590282Sobrien      convert_to_ssa ();
265690282Sobrien
265790282Sobrien      close_dump_file (DFI_ssa, print_rtl_with_bb, insns);
265890282Sobrien      timevar_pop (TV_TO_SSA);
265990282Sobrien
266090282Sobrien      /* Perform sparse conditional constant propagation, if requested.  */
266190282Sobrien      if (flag_ssa_ccp)
266290282Sobrien	{
266390282Sobrien	  timevar_push (TV_SSA_CCP);
266490282Sobrien	  open_dump_file (DFI_ssa_ccp, decl);
266590282Sobrien
266690282Sobrien	  ssa_const_prop ();
266790282Sobrien
266890282Sobrien	  close_dump_file (DFI_ssa_ccp, print_rtl_with_bb, get_insns ());
266990282Sobrien	  timevar_pop (TV_SSA_CCP);
267090282Sobrien	}
267190282Sobrien
267290282Sobrien      /* It would be useful to cleanup the CFG at this point, but block
267390282Sobrien	 merging and possibly other transformations might leave a PHI
267490282Sobrien	 node in the middle of a basic block, which is a strict no-no.  */
267590282Sobrien
267690282Sobrien      /* The SSA implementation uses basic block numbers in its phi
267790282Sobrien	 nodes.  Thus, changing the control-flow graph or the basic
267890282Sobrien	 blocks, e.g., calling find_basic_blocks () or cleanup_cfg (),
267990282Sobrien	 may cause problems.  */
268090282Sobrien
268190282Sobrien      if (flag_ssa_dce)
268290282Sobrien	{
268390282Sobrien	  /* Remove dead code.  */
268490282Sobrien
268590282Sobrien	  timevar_push (TV_SSA_DCE);
268690282Sobrien	  open_dump_file (DFI_ssa_dce, decl);
268790282Sobrien
268890282Sobrien	  insns = get_insns ();
268990282Sobrien	  ssa_eliminate_dead_code();
269090282Sobrien
269190282Sobrien	  close_dump_file (DFI_ssa_dce, print_rtl_with_bb, insns);
269290282Sobrien	  timevar_pop (TV_SSA_DCE);
269390282Sobrien	}
269490282Sobrien
269590282Sobrien      /* Convert from SSA form.  */
269690282Sobrien
269790282Sobrien      timevar_push (TV_FROM_SSA);
269890282Sobrien      open_dump_file (DFI_ussa, decl);
269990282Sobrien
270090282Sobrien      convert_from_ssa ();
270190282Sobrien      /* New registers have been created.  Rescan their usage.  */
270290282Sobrien      reg_scan (insns, max_reg_num (), 1);
270390282Sobrien
270490282Sobrien      close_dump_file (DFI_ussa, print_rtl_with_bb, insns);
270590282Sobrien      timevar_pop (TV_FROM_SSA);
270690282Sobrien
270790282Sobrien      ggc_collect ();
270890282Sobrien      /* CFG is no longer maintained up-to-date.  */
270990282Sobrien      free_bb_for_insn ();
271090282Sobrien    }
271190282Sobrien
271290282Sobrien  timevar_push (TV_JUMP);
271390282Sobrien
271490282Sobrien  if (optimize > 0)
271590282Sobrien    {
271690282Sobrien      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
271790282Sobrien      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP
271890282Sobrien 		   | (flag_thread_jumps ? CLEANUP_THREADING : 0));
271990282Sobrien
272090282Sobrien      /* ??? Run if-conversion before delete_null_pointer_checks,
272190282Sobrien         since the later does not preserve the CFG.  This should
272290282Sobrien	 be changed -- no since converting if's that are going to
272390282Sobrien	 be deleted.  */
272490282Sobrien      timevar_push (TV_IFCVT);
272590282Sobrien      if_convert (0);
272690282Sobrien      timevar_pop (TV_IFCVT);
272790282Sobrien
272890282Sobrien      /* CFG is no longer maintained up-to-date.  */
272990282Sobrien      free_bb_for_insn ();
273090282Sobrien      /* Try to identify useless null pointer tests and delete them.  */
273190282Sobrien      if (flag_delete_null_pointer_checks)
273290282Sobrien	delete_null_pointer_checks (insns);
273390282Sobrien    }
273490282Sobrien
273590282Sobrien  /* Jump optimization, and the removal of NULL pointer checks, may
273690282Sobrien     have reduced the number of instructions substantially.  CSE, and
273790282Sobrien     future passes, allocate arrays whose dimensions involve the
273890282Sobrien     maximum instruction UID, so if we can reduce the maximum UID
273990282Sobrien     we'll save big on memory.  */
274090282Sobrien  renumber_insns (rtl_dump_file);
274190282Sobrien  timevar_pop (TV_JUMP);
274290282Sobrien
274390282Sobrien  close_dump_file (DFI_jump, print_rtl, insns);
274490282Sobrien
274590282Sobrien  ggc_collect ();
274690282Sobrien
274718334Speter  /* Perform common subexpression elimination.
274818334Speter     Nonzero value from `cse_main' means that jumps were simplified
274918334Speter     and some code may now be unreachable, so do
275018334Speter     jump optimization again.  */
275118334Speter
275218334Speter  if (optimize > 0)
275318334Speter    {
275490282Sobrien      open_dump_file (DFI_cse, decl);
275590282Sobrien      timevar_push (TV_CSE);
275650615Sobrien
275790282Sobrien      reg_scan (insns, max_reg_num (), 1);
275818334Speter
275990282Sobrien      tem = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
276018334Speter
276190282Sobrien      /* If we are not running more CSE passes, then we are no longer
276290282Sobrien	 expecting CSE to be run.  But always rerun it in a cheap mode.  */
276390282Sobrien      cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse;
276490282Sobrien
276518334Speter      if (tem || optimize > 1)
276690282Sobrien	{
276790282Sobrien	  timevar_push (TV_JUMP);
276890282Sobrien	  rebuild_jump_labels (insns);
276990282Sobrien	  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
277090282Sobrien	  cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
277190282Sobrien	  timevar_pop (TV_JUMP);
277290282Sobrien	  /* CFG is no longer maintained up-to-date.  */
277390282Sobrien	  free_bb_for_insn ();
277490282Sobrien	}
277550615Sobrien
277656392Sobrien      /* Run this after jump optmizations remove all the unreachable code
277756392Sobrien	 so that unreachable code will not keep values live.  */
277890282Sobrien      delete_trivially_dead_insns (insns, max_reg_num (), 0);
277956392Sobrien
278090282Sobrien      /* Try to identify useless null pointer tests and delete them.  */
278190282Sobrien      if (flag_delete_null_pointer_checks || flag_thread_jumps)
278290282Sobrien	{
278390282Sobrien	  timevar_push (TV_JUMP);
278490282Sobrien	  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
278552558Sobrien
278690282Sobrien	  cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP
278790282Sobrien		       | (flag_thread_jumps ? CLEANUP_THREADING : 0));
278890282Sobrien
278990282Sobrien	  if (flag_delete_null_pointer_checks)
279090282Sobrien	    delete_null_pointer_checks (insns);
279190282Sobrien	  /* CFG is no longer maintained up-to-date.  */
279290282Sobrien	  free_bb_for_insn ();
279390282Sobrien	  timevar_pop (TV_JUMP);
279452558Sobrien	}
279590282Sobrien
279690282Sobrien      /* The second pass of jump optimization is likely to have
279790282Sobrien         removed a bunch more instructions.  */
279890282Sobrien      renumber_insns (rtl_dump_file);
279990282Sobrien
280090282Sobrien      timevar_pop (TV_CSE);
280190282Sobrien      close_dump_file (DFI_cse, print_rtl, insns);
280218334Speter    }
280318334Speter
280490282Sobrien  open_dump_file (DFI_addressof, decl);
280590282Sobrien
280650615Sobrien  purge_addressof (insns);
280750615Sobrien  reg_scan (insns, max_reg_num (), 1);
280818334Speter
280990282Sobrien  close_dump_file (DFI_addressof, print_rtl, insns);
281052558Sobrien
281190282Sobrien  ggc_collect ();
281290282Sobrien
281350615Sobrien  /* Perform global cse.  */
281418334Speter
281550615Sobrien  if (optimize > 0 && flag_gcse)
281650615Sobrien    {
281790282Sobrien      int save_csb, save_cfj;
281890282Sobrien      int tem2 = 0;
281918334Speter
282090282Sobrien      timevar_push (TV_GCSE);
282190282Sobrien      open_dump_file (DFI_gcse, decl);
282252558Sobrien
282390282Sobrien      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
282490282Sobrien      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
282590282Sobrien      tem = gcse_main (insns, rtl_dump_file);
282690282Sobrien      rebuild_jump_labels (insns);
282790282Sobrien
282890282Sobrien      save_csb = flag_cse_skip_blocks;
282990282Sobrien      save_cfj = flag_cse_follow_jumps;
283090282Sobrien      flag_cse_skip_blocks = flag_cse_follow_jumps = 0;
283190282Sobrien
283290282Sobrien      /* CFG is no longer maintained up-to-date.  */
283390282Sobrien      free_bb_for_insn ();
283490282Sobrien      /* If -fexpensive-optimizations, re-run CSE to clean up things done
283590282Sobrien	 by gcse.  */
283690282Sobrien      if (flag_expensive_optimizations)
283752558Sobrien	{
283890282Sobrien	  timevar_push (TV_CSE);
283990282Sobrien	  reg_scan (insns, max_reg_num (), 1);
284090282Sobrien	  tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
284190282Sobrien	  timevar_pop (TV_CSE);
284290282Sobrien	  cse_not_expected = !flag_rerun_cse_after_loop;
284390282Sobrien	}
284452558Sobrien
284590282Sobrien      /* If gcse or cse altered any jumps, rerun jump optimizations to clean
284690282Sobrien	 things up.  Then possibly re-run CSE again.  */
284790282Sobrien      while (tem || tem2)
284852558Sobrien	{
284990282Sobrien	  tem = tem2 = 0;
285090282Sobrien	  timevar_push (TV_JUMP);
285190282Sobrien	  rebuild_jump_labels (insns);
285290282Sobrien	  delete_trivially_dead_insns (insns, max_reg_num (), 0);
285390282Sobrien	  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
285490282Sobrien	  cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
285590282Sobrien	  /* CFG is no longer maintained up-to-date.  */
285690282Sobrien	  free_bb_for_insn ();
285790282Sobrien	  timevar_pop (TV_JUMP);
285890282Sobrien
285990282Sobrien	  if (flag_expensive_optimizations)
286090282Sobrien	    {
286190282Sobrien	      timevar_push (TV_CSE);
286290282Sobrien	      reg_scan (insns, max_reg_num (), 1);
286390282Sobrien	      tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
286490282Sobrien	      timevar_pop (TV_CSE);
286590282Sobrien	    }
286652558Sobrien	}
286790282Sobrien
286890282Sobrien      close_dump_file (DFI_gcse, print_rtl, insns);
286990282Sobrien      timevar_pop (TV_GCSE);
287090282Sobrien
287190282Sobrien      ggc_collect ();
287290282Sobrien      flag_cse_skip_blocks = save_csb;
287390282Sobrien      flag_cse_follow_jumps = save_cfj;
287450615Sobrien    }
287590282Sobrien
287618334Speter  /* Move constant computations out of loops.  */
287718334Speter
287818334Speter  if (optimize > 0)
287918334Speter    {
288090282Sobrien      timevar_push (TV_LOOP);
288190282Sobrien      open_dump_file (DFI_loop, decl);
288290282Sobrien      free_bb_for_insn ();
288318334Speter
288490282Sobrien      if (flag_rerun_loop_opt)
288590282Sobrien	{
288690282Sobrien	  cleanup_barriers ();
288790282Sobrien
288890282Sobrien	  /* We only want to perform unrolling once.  */
288996289Sobrien	  loop_optimize (insns, rtl_dump_file, LOOP_FIRST_PASS);
289090282Sobrien
289190282Sobrien	  /* The first call to loop_optimize makes some instructions
289290282Sobrien	     trivially dead.  We delete those instructions now in the
289390282Sobrien	     hope that doing so will make the heuristics in loop work
289490282Sobrien	     better and possibly speed up compilation.  */
289590282Sobrien	  delete_trivially_dead_insns (insns, max_reg_num (), 0);
289690282Sobrien
289790282Sobrien	  /* The regscan pass is currently necessary as the alias
289850615Sobrien		  analysis code depends on this information.  */
289990282Sobrien	  reg_scan (insns, max_reg_num (), 1);
290090282Sobrien	}
290190282Sobrien      cleanup_barriers ();
290290282Sobrien      loop_optimize (insns, rtl_dump_file,
290390282Sobrien		     (flag_unroll_loops ? LOOP_UNROLL : 0) | LOOP_BCT
290490282Sobrien		     | (flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0));
290552558Sobrien
290690282Sobrien      close_dump_file (DFI_loop, print_rtl, insns);
290790282Sobrien      timevar_pop (TV_LOOP);
290852558Sobrien
290990282Sobrien      ggc_collect ();
291050615Sobrien    }
291118334Speter
291250615Sobrien  if (optimize > 0)
291318334Speter    {
291490282Sobrien      timevar_push (TV_CSE2);
291590282Sobrien      open_dump_file (DFI_cse2, decl);
291652558Sobrien
291750615Sobrien      if (flag_rerun_cse_after_loop)
291850615Sobrien	{
291950615Sobrien	  /* Running another jump optimization pass before the second
292050615Sobrien	     cse pass sometimes simplifies the RTL enough to allow
292150615Sobrien	     the second CSE pass to do a better job.  Jump_optimize can change
292250615Sobrien	     max_reg_num so we must rerun reg_scan afterwards.
292350615Sobrien	     ??? Rework to not call reg_scan so often.  */
292490282Sobrien	  timevar_push (TV_JUMP);
292590282Sobrien
292690282Sobrien	  /* The previous call to loop_optimize makes some instructions
292790282Sobrien	     trivially dead.  We delete those instructions now in the
292890282Sobrien	     hope that doing so will make the heuristics in jump work
292990282Sobrien	     better and possibly speed up compilation.  */
293090282Sobrien	  delete_trivially_dead_insns (insns, max_reg_num (), 0);
293190282Sobrien
293290282Sobrien	  reg_scan (insns, max_reg_num (), 0);
293390282Sobrien
293490282Sobrien	  timevar_push (TV_IFCVT);
293590282Sobrien
293690282Sobrien	  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
293790282Sobrien	  cleanup_cfg (CLEANUP_EXPENSIVE);
293890282Sobrien	  if_convert (0);
293990282Sobrien
294090282Sobrien	  timevar_pop(TV_IFCVT);
294190282Sobrien
294290282Sobrien	  timevar_pop (TV_JUMP);
294390282Sobrien
294490282Sobrien	  /* CFG is no longer maintained up-to-date.  */
294590282Sobrien	  free_bb_for_insn ();
294690282Sobrien	  reg_scan (insns, max_reg_num (), 0);
294790282Sobrien	  tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file);
294890282Sobrien
294950615Sobrien	  if (tem)
295090282Sobrien	    {
295190282Sobrien	      timevar_push (TV_JUMP);
295290282Sobrien	      rebuild_jump_labels (insns);
295390282Sobrien	      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
295490282Sobrien	      cleanup_cfg (CLEANUP_EXPENSIVE);
295590282Sobrien	      /* CFG is no longer maintained up-to-date.  */
295690282Sobrien	      free_bb_for_insn ();
295790282Sobrien	      timevar_pop (TV_JUMP);
295890282Sobrien	    }
295950615Sobrien	}
296018334Speter
296190282Sobrien      close_dump_file (DFI_cse2, print_rtl, insns);
296290282Sobrien      timevar_pop (TV_CSE2);
296352558Sobrien
296490282Sobrien      ggc_collect ();
296518334Speter    }
296652558Sobrien
296790282Sobrien  cse_not_expected = 1;
296890282Sobrien
296990282Sobrien  regclass_init ();
297090282Sobrien
297190282Sobrien  /* Do control and data flow analysis; wrote some of the results to
297290282Sobrien     the dump file.  */
297390282Sobrien
297490282Sobrien  timevar_push (TV_FLOW);
297590282Sobrien  open_dump_file (DFI_cfg, decl);
297690282Sobrien
297790282Sobrien  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
297890282Sobrien  cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0)
297990282Sobrien	       | (flag_thread_jumps ? CLEANUP_THREADING : 0));
298090282Sobrien  check_function_return_warnings ();
298190282Sobrien
298290282Sobrien  /* It may make more sense to mark constant functions after dead code is
298390282Sobrien     eliminated by life_analyzis, but we need to do it early, as -fprofile-arcs
298490282Sobrien     may insert code making function non-constant, but we still must consider
298590282Sobrien     it as constant, otherwise -fbranch-probabilities will not read data back.
298690282Sobrien
298790282Sobrien     life_analyzis rarely eliminates modification of external memory.
298890282Sobrien   */
298990282Sobrien  mark_constant_function ();
299090282Sobrien
299190282Sobrien  close_dump_file (DFI_cfg, print_rtl_with_bb, insns);
299290282Sobrien
299350615Sobrien  if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
299450615Sobrien    {
299590282Sobrien      timevar_push (TV_BRANCH_PROB);
299690282Sobrien      open_dump_file (DFI_bp, decl);
299752558Sobrien
299890282Sobrien      branch_prob ();
299952558Sobrien
300090282Sobrien      close_dump_file (DFI_bp, print_rtl_with_bb, insns);
300190282Sobrien      timevar_pop (TV_BRANCH_PROB);
300250615Sobrien    }
300352558Sobrien
300490282Sobrien  open_dump_file (DFI_life, decl);
300590282Sobrien  if (optimize)
300690282Sobrien    {
300790282Sobrien      struct loops loops;
300818334Speter
300990282Sobrien      /* Discover and record the loop depth at the head of each basic
301090282Sobrien	 block.  The loop infrastructure does the real job for us.  */
301190282Sobrien      flow_loops_find (&loops, LOOP_TREE);
301218334Speter
301390282Sobrien      /* Estimate using heuristics if no profiling info is available.  */
301490282Sobrien      if (flag_guess_branch_prob)
301590282Sobrien	estimate_probability (&loops);
301618334Speter
301790282Sobrien      if (rtl_dump_file)
301890282Sobrien	flow_loops_dump (&loops, rtl_dump_file, NULL, 0);
301918334Speter
302090282Sobrien      flow_loops_free (&loops);
302190282Sobrien    }
302290282Sobrien  life_analysis (insns, rtl_dump_file, PROP_FINAL);
302390282Sobrien  timevar_pop (TV_FLOW);
302418334Speter
302590282Sobrien  no_new_pseudos = 1;
302618334Speter
302790282Sobrien  if (warn_uninitialized || extra_warnings)
302818334Speter    {
302990282Sobrien      uninitialized_vars_warning (DECL_INITIAL (decl));
303090282Sobrien      if (extra_warnings)
303190282Sobrien	setjmp_args_warning ();
303218334Speter    }
303390282Sobrien
303490282Sobrien  if (optimize)
303518334Speter    {
303690282Sobrien      if (initialize_uninitialized_subregs ())
303718334Speter	{
303890282Sobrien	  /* Insns were inserted, so things might look a bit different.  */
303990282Sobrien	  insns = get_insns ();
304090282Sobrien	  life_analysis (insns, rtl_dump_file,
304190282Sobrien			 (PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES));
304218334Speter	}
304318334Speter    }
304418334Speter
304590282Sobrien  close_dump_file (DFI_life, print_rtl_with_bb, insns);
304618334Speter
304790282Sobrien  ggc_collect ();
304852558Sobrien
304918334Speter  /* If -opt, try combining insns through substitution.  */
305018334Speter
305118334Speter  if (optimize > 0)
305250615Sobrien    {
305390282Sobrien      int rebuild_jump_labels_after_combine = 0;
305452558Sobrien
305590282Sobrien      timevar_push (TV_COMBINE);
305690282Sobrien      open_dump_file (DFI_combine, decl);
305752558Sobrien
305890282Sobrien      rebuild_jump_labels_after_combine
305990282Sobrien	= combine_instructions (insns, max_reg_num ());
306090282Sobrien
306190282Sobrien      /* Always purge dead edges, as we may eliminate an insn throwing
306290282Sobrien         exception.  */
306390282Sobrien      rebuild_jump_labels_after_combine |= purge_all_dead_edges (true);
306490282Sobrien
306590282Sobrien      /* Combining insns may have turned an indirect jump into a
306690282Sobrien	 direct jump.  Rebuid the JUMP_LABEL fields of jumping
306790282Sobrien	 instructions.  */
306890282Sobrien      if (rebuild_jump_labels_after_combine)
306952558Sobrien	{
307090282Sobrien	  timevar_push (TV_JUMP);
307190282Sobrien	  rebuild_jump_labels (insns);
307290282Sobrien	  timevar_pop (TV_JUMP);
307390282Sobrien
307490282Sobrien	  cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE);
307552558Sobrien	}
307690282Sobrien
307790282Sobrien      close_dump_file (DFI_combine, print_rtl_with_bb, insns);
307890282Sobrien      timevar_pop (TV_COMBINE);
307990282Sobrien
308090282Sobrien      ggc_collect ();
308150615Sobrien    }
308218334Speter
308390282Sobrien  /* Rerun if-conversion, as combine may have simplified things enough to
308490282Sobrien     now meet sequence length restrictions.  */
308590282Sobrien  if (optimize > 0)
308690282Sobrien    {
308790282Sobrien      timevar_push (TV_IFCVT);
308890282Sobrien      open_dump_file (DFI_ce, decl);
308990282Sobrien
309090282Sobrien      no_new_pseudos = 0;
309190282Sobrien      if_convert (1);
309290282Sobrien      no_new_pseudos = 1;
309390282Sobrien
309490282Sobrien      close_dump_file (DFI_ce, print_rtl_with_bb, insns);
309590282Sobrien      timevar_pop (TV_IFCVT);
309690282Sobrien    }
309790282Sobrien
309850615Sobrien  /* Register allocation pre-pass, to reduce number of moves
309950615Sobrien     necessary for two-address machines.  */
310050615Sobrien  if (optimize > 0 && (flag_regmove || flag_expensive_optimizations))
310150615Sobrien    {
310290282Sobrien      timevar_push (TV_REGMOVE);
310390282Sobrien      open_dump_file (DFI_regmove, decl);
310452558Sobrien
310590282Sobrien      regmove_optimize (insns, max_reg_num (), rtl_dump_file);
310652558Sobrien
310790282Sobrien      close_dump_file (DFI_regmove, print_rtl_with_bb, insns);
310890282Sobrien      timevar_pop (TV_REGMOVE);
310990282Sobrien
311090282Sobrien      ggc_collect ();
311150615Sobrien    }
311218334Speter
311390282Sobrien  /* Do unconditional splitting before register allocation to allow machine
311490282Sobrien     description to add extra information not needed previously.  */
311590282Sobrien  split_all_insns (1);
311690282Sobrien
311790282Sobrien  /* Any of the several passes since flow1 will have munged register
311890282Sobrien     lifetime data a bit.  */
311990282Sobrien  register_life_up_to_date = 0;
312090282Sobrien
312190282Sobrien#ifdef OPTIMIZE_MODE_SWITCHING
312290282Sobrien  timevar_push (TV_MODE_SWITCH);
312390282Sobrien
312490282Sobrien  no_new_pseudos = 0;
312590282Sobrien  if (optimize_mode_switching (NULL))
312690282Sobrien    {
312790282Sobrien      /* We did work, and so had to regenerate global life information.
312890282Sobrien	 Take advantage of this and don't re-recompute register life
312990282Sobrien	 information below.  */
313090282Sobrien      register_life_up_to_date = 1;
313190282Sobrien    }
313290282Sobrien  no_new_pseudos = 1;
313390282Sobrien
313490282Sobrien  timevar_pop (TV_MODE_SWITCH);
313590282Sobrien#endif
313690282Sobrien
313790282Sobrien  timevar_push (TV_SCHED);
313890282Sobrien
313990282Sobrien#ifdef INSN_SCHEDULING
314090282Sobrien
314118334Speter  /* Print function header into sched dump now
314218334Speter     because doing the sched analysis makes some of the dump.  */
314318334Speter  if (optimize > 0 && flag_schedule_insns)
314418334Speter    {
314590282Sobrien      open_dump_file (DFI_sched, decl);
314652558Sobrien
314718334Speter      /* Do control and data sched analysis,
314818334Speter	 and write some of the results to dump file.  */
314918334Speter
315090282Sobrien      schedule_insns (rtl_dump_file);
315152558Sobrien
315290282Sobrien      close_dump_file (DFI_sched, print_rtl_with_bb, insns);
315352558Sobrien
315490282Sobrien      /* Register lifetime information was updated as part of verifying
315590282Sobrien	 the schedule.  */
315690282Sobrien      register_life_up_to_date = 1;
315718334Speter    }
315890282Sobrien#endif
315990282Sobrien  timevar_pop (TV_SCHED);
316018334Speter
316190282Sobrien  ggc_collect ();
316290282Sobrien
316352558Sobrien  /* Determine if the current function is a leaf before running reload
316452558Sobrien     since this can impact optimizations done by the prologue and
316552558Sobrien     epilogue thus changing register elimination offsets.  */
316652558Sobrien  current_function_is_leaf = leaf_function_p ();
316752558Sobrien
316890282Sobrien  timevar_push (TV_LOCAL_ALLOC);
316990282Sobrien  open_dump_file (DFI_lreg, decl);
317018334Speter
317190282Sobrien  /* Allocate pseudo-regs that are used only within 1 basic block.
317290282Sobrien
317352558Sobrien     RUN_JUMP_AFTER_RELOAD records whether or not we need to rerun the
317452558Sobrien     jump optimizer after register allocation and reloading are finished.  */
317552558Sobrien
317690282Sobrien  if (! register_life_up_to_date)
317790282Sobrien    recompute_reg_usage (insns, ! optimize_size);
317818334Speter
317990282Sobrien  /* Allocate the reg_renumber array.  */
318090282Sobrien  allocate_reg_info (max_regno, FALSE, TRUE);
318118334Speter
318290282Sobrien  /* And the reg_equiv_memory_loc array.  */
318390282Sobrien  reg_equiv_memory_loc = (rtx *) xcalloc (max_regno, sizeof (rtx));
318490282Sobrien
318590282Sobrien  allocate_initial_values (reg_equiv_memory_loc);
318690282Sobrien
318790282Sobrien  regclass (insns, max_reg_num (), rtl_dump_file);
318890282Sobrien  rebuild_label_notes_after_reload = local_alloc ();
318990282Sobrien
319090282Sobrien  timevar_pop (TV_LOCAL_ALLOC);
319190282Sobrien
319290282Sobrien  if (dump_file[DFI_lreg].enabled)
319350615Sobrien    {
319490282Sobrien      timevar_push (TV_DUMP);
319552558Sobrien
319690282Sobrien      dump_flow_info (rtl_dump_file);
319790282Sobrien      dump_local_alloc (rtl_dump_file);
319852558Sobrien
319990282Sobrien      close_dump_file (DFI_lreg, print_rtl_with_bb, insns);
320090282Sobrien      timevar_pop (TV_DUMP);
320150615Sobrien    }
320218334Speter
320390282Sobrien  ggc_collect ();
320418334Speter
320590282Sobrien  timevar_push (TV_GLOBAL_ALLOC);
320690282Sobrien  open_dump_file (DFI_greg, decl);
320718334Speter
320890282Sobrien  /* If optimizing, allocate remaining pseudo-regs.  Do the reload
320990282Sobrien     pass fixing up any insns that are invalid.  */
321018334Speter
321190282Sobrien  if (optimize)
321290282Sobrien    failure = global_alloc (rtl_dump_file);
321390282Sobrien  else
321490282Sobrien    {
321590282Sobrien      build_insn_chain (insns);
321690282Sobrien      failure = reload (insns, 0);
321790282Sobrien    }
321818334Speter
321990282Sobrien  timevar_pop (TV_GLOBAL_ALLOC);
322090282Sobrien
322190282Sobrien  if (dump_file[DFI_greg].enabled)
322290282Sobrien    {
322390282Sobrien      timevar_push (TV_DUMP);
322490282Sobrien
322590282Sobrien      dump_global_regs (rtl_dump_file);
322690282Sobrien
322790282Sobrien      close_dump_file (DFI_greg, print_rtl_with_bb, insns);
322890282Sobrien      timevar_pop (TV_DUMP);
322990282Sobrien    }
323090282Sobrien
323118334Speter  if (failure)
323218334Speter    goto exit_rest_of_compilation;
323318334Speter
323490282Sobrien  ggc_collect ();
323590282Sobrien
323690282Sobrien  open_dump_file (DFI_postreload, decl);
323790282Sobrien
323850615Sobrien  /* Do a very simple CSE pass over just the hard registers.  */
323950615Sobrien  if (optimize > 0)
324090282Sobrien    {
324190282Sobrien      timevar_push (TV_RELOAD_CSE_REGS);
324290282Sobrien      reload_cse_regs (insns);
324390282Sobrien      timevar_pop (TV_RELOAD_CSE_REGS);
324490282Sobrien    }
324550615Sobrien
324652558Sobrien  /* Register allocation and reloading may have turned an indirect jump into
324752558Sobrien     a direct jump.  If so, we must rebuild the JUMP_LABEL fields of
324852558Sobrien     jumping instructions.  */
324952558Sobrien  if (rebuild_label_notes_after_reload)
325090282Sobrien    {
325190282Sobrien      timevar_push (TV_JUMP);
325252558Sobrien
325390282Sobrien      rebuild_jump_labels (insns);
325452558Sobrien
325590282Sobrien      timevar_pop (TV_JUMP);
325690282Sobrien    }
325752558Sobrien
325890282Sobrien  close_dump_file (DFI_postreload, print_rtl_with_bb, insns);
325952558Sobrien
326090282Sobrien  /* Re-create the death notes which were deleted during reload.  */
326190282Sobrien  timevar_push (TV_FLOW2);
326290282Sobrien  open_dump_file (DFI_flow2, decl);
326352558Sobrien
326490282Sobrien#ifdef ENABLE_CHECKING
326590282Sobrien  verify_flow_info ();
326690282Sobrien#endif
326752558Sobrien
326890282Sobrien  /* If optimizing, then go ahead and split insns now.  */
326990282Sobrien  if (optimize > 0)
327090282Sobrien    split_all_insns (0);
327152558Sobrien
327290282Sobrien  cleanup_cfg (optimize ? CLEANUP_EXPENSIVE : 0);
327352558Sobrien
327490282Sobrien  /* On some machines, the prologue and epilogue code, or parts thereof,
327590282Sobrien     can be represented as RTL.  Doing so lets us schedule insns between
327690282Sobrien     it and the rest of the code and also allows delayed branch
327790282Sobrien     scheduling to operate in the epilogue.  */
327890282Sobrien  thread_prologue_and_epilogue_insns (insns);
327990282Sobrien
328096289Sobrien  /* Cross-jumping is O(N^3) on the number of edges, thus trying to
328196289Sobrien     perform cross-jumping on flow graphs which have a high connectivity
328296289Sobrien     will take a long time.  This is similar to the test to disable GCSE.  */
328396289Sobrien  cleanup_crossjump = CLEANUP_CROSSJUMP;
328496289Sobrien  if (n_basic_blocks > 1000 && n_edges / n_basic_blocks >= 20)
328596289Sobrien    {
328696289Sobrien      if (optimize && warn_disabled_optimization)
328796289Sobrien	warning ("crossjump disabled: %d > 1000 basic blocks and %d >= 20 edges/basic block",
328896289Sobrien                 n_basic_blocks, n_edges / n_basic_blocks);
328996289Sobrien      cleanup_crossjump = 0;
329096289Sobrien    }
329196289Sobrien
329252558Sobrien  if (optimize)
329352558Sobrien    {
329496289Sobrien      cleanup_cfg (CLEANUP_EXPENSIVE | cleanup_crossjump);
329590282Sobrien      life_analysis (insns, rtl_dump_file, PROP_FINAL);
329690282Sobrien
329790282Sobrien      /* This is kind of a heuristic.  We need to run combine_stack_adjustments
329890282Sobrien         even for machines with possibly nonzero RETURN_POPS_ARGS
329990282Sobrien         and ACCUMULATE_OUTGOING_ARGS.  We expect that only ports having
330090282Sobrien         push instructions will have popping returns.  */
330190282Sobrien#ifndef PUSH_ROUNDING
330290282Sobrien      if (!ACCUMULATE_OUTGOING_ARGS)
330390282Sobrien#endif
330490282Sobrien	combine_stack_adjustments ();
330590282Sobrien
330690282Sobrien      ggc_collect ();
330752558Sobrien    }
330852558Sobrien
330952558Sobrien  flow2_completed = 1;
331052558Sobrien
331190282Sobrien  close_dump_file (DFI_flow2, print_rtl_with_bb, insns);
331290282Sobrien  timevar_pop (TV_FLOW2);
331318334Speter
331490282Sobrien#ifdef HAVE_peephole2
331590282Sobrien  if (optimize > 0 && flag_peephole2)
331690282Sobrien    {
331790282Sobrien      timevar_push (TV_PEEPHOLE2);
331890282Sobrien      open_dump_file (DFI_peephole2, decl);
331918334Speter
332090282Sobrien      peephole2_optimize (rtl_dump_file);
332190282Sobrien
332290282Sobrien      close_dump_file (DFI_peephole2, print_rtl_with_bb, insns);
332390282Sobrien      timevar_pop (TV_PEEPHOLE2);
332490282Sobrien    }
332590282Sobrien#endif
332690282Sobrien
332796289Sobrien  if (optimize > 0 && (flag_rename_registers || flag_cprop_registers))
332850615Sobrien    {
332990282Sobrien      timevar_push (TV_RENAME_REGISTERS);
333090282Sobrien      open_dump_file (DFI_rnreg, decl);
333190282Sobrien
333290282Sobrien      if (flag_rename_registers)
333390282Sobrien        regrename_optimize ();
333490282Sobrien      if (flag_cprop_registers)
333590282Sobrien        copyprop_hardreg_forward ();
333690282Sobrien
333790282Sobrien      close_dump_file (DFI_rnreg, print_rtl_with_bb, insns);
333890282Sobrien      timevar_pop (TV_RENAME_REGISTERS);
333950615Sobrien    }
334052558Sobrien
334190282Sobrien  if (optimize > 0)
334290282Sobrien    {
334390282Sobrien      timevar_push (TV_IFCVT2);
334490282Sobrien      open_dump_file (DFI_ce2, decl);
334590282Sobrien
334690282Sobrien      if_convert (1);
334790282Sobrien
334890282Sobrien      close_dump_file (DFI_ce2, print_rtl_with_bb, insns);
334990282Sobrien      timevar_pop (TV_IFCVT2);
335090282Sobrien    }
335190282Sobrien#ifdef STACK_REGS
335290282Sobrien  if (optimize)
335390282Sobrien    split_all_insns (1);
335490282Sobrien#endif
335590282Sobrien
335690282Sobrien#ifdef INSN_SCHEDULING
335718334Speter  if (optimize > 0 && flag_schedule_insns_after_reload)
335818334Speter    {
335990282Sobrien      timevar_push (TV_SCHED2);
336090282Sobrien      open_dump_file (DFI_sched2, decl);
336118334Speter
336218334Speter      /* Do control and data sched analysis again,
336318334Speter	 and write some more of the results to dump file.  */
336418334Speter
336590282Sobrien      split_all_insns (1);
336618334Speter
336790282Sobrien      schedule_insns (rtl_dump_file);
336818334Speter
336990282Sobrien      close_dump_file (DFI_sched2, print_rtl_with_bb, insns);
337090282Sobrien      timevar_pop (TV_SCHED2);
337190282Sobrien
337290282Sobrien      ggc_collect ();
337318334Speter    }
337490282Sobrien#endif
337518334Speter
337618334Speter#ifdef LEAF_REGISTERS
337752558Sobrien  current_function_uses_only_leaf_regs
337852558Sobrien    = optimize > 0 && only_leaf_regs_used () && leaf_function_p ();
337918334Speter#endif
338018334Speter
338190282Sobrien#ifdef STACK_REGS
338290282Sobrien  timevar_push (TV_REG_STACK);
338390282Sobrien  open_dump_file (DFI_stack, decl);
338418334Speter
338590282Sobrien  reg_to_stack (insns, rtl_dump_file);
338690282Sobrien
338790282Sobrien  close_dump_file (DFI_stack, print_rtl_with_bb, insns);
338890282Sobrien  timevar_pop (TV_REG_STACK);
338990282Sobrien
339090282Sobrien  ggc_collect ();
339190282Sobrien#endif
339218334Speter  if (optimize > 0)
339318334Speter    {
339490282Sobrien      timevar_push (TV_REORDER_BLOCKS);
339590282Sobrien      open_dump_file (DFI_bbro, decl);
339652558Sobrien
339796289Sobrien      /* Last attempt to optimize CFG, as life analysis possibly removed
339896289Sobrien	 some instructions.  Note that we can't rerun crossjump at this
339996289Sobrien	 point, because it can turn a switch into a direct branch, which
340096289Sobrien	 can leave the tablejump address calculation in the code, which
340196289Sobrien	 can lead to referencing an undefined label.  */
340296289Sobrien      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
340390282Sobrien      if (flag_reorder_blocks)
340452558Sobrien	{
340590282Sobrien	  reorder_basic_blocks ();
340690282Sobrien	  cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
340752558Sobrien	}
340890282Sobrien
340990282Sobrien      close_dump_file (DFI_bbro, print_rtl_with_bb, insns);
341090282Sobrien      timevar_pop (TV_REORDER_BLOCKS);
341118334Speter    }
341290282Sobrien  compute_alignments ();
341318334Speter
341490282Sobrien  /* CFG is no longer maintained up-to-date.  */
341590282Sobrien  free_bb_for_insn ();
341690282Sobrien
341718334Speter  /* If a machine dependent reorganization is needed, call it.  */
341818334Speter#ifdef MACHINE_DEPENDENT_REORG
341990282Sobrien  timevar_push (TV_MACH_DEP);
342090282Sobrien  open_dump_file (DFI_mach, decl);
342150615Sobrien
342290282Sobrien  MACHINE_DEPENDENT_REORG (insns);
342390282Sobrien
342490282Sobrien  close_dump_file (DFI_mach, print_rtl, insns);
342590282Sobrien  timevar_pop (TV_MACH_DEP);
342690282Sobrien
342790282Sobrien  ggc_collect ();
342818334Speter#endif
342918334Speter
343090282Sobrien  purge_line_number_notes (insns);
343190282Sobrien  cleanup_barriers ();
343290282Sobrien
343318334Speter  /* If a scheduling pass for delayed branches is to be done,
343450615Sobrien     call the scheduling code.  */
343518334Speter
343618334Speter#ifdef DELAY_SLOTS
343718334Speter  if (optimize > 0 && flag_delayed_branch)
343818334Speter    {
343990282Sobrien      timevar_push (TV_DBR_SCHED);
344090282Sobrien      open_dump_file (DFI_dbr, decl);
344152558Sobrien
344290282Sobrien      dbr_schedule (insns, rtl_dump_file);
344352558Sobrien
344490282Sobrien      close_dump_file (DFI_dbr, print_rtl, insns);
344590282Sobrien      timevar_pop (TV_DBR_SCHED);
344690282Sobrien
344790282Sobrien      ggc_collect ();
344818334Speter    }
344918334Speter#endif
345018334Speter
345190282Sobrien#if defined (HAVE_ATTR_length) && !defined (STACK_REGS)
345290282Sobrien  timevar_push (TV_SHORTEN_BRANCH);
345390282Sobrien  split_all_insns_noflow ();
345490282Sobrien  timevar_pop (TV_SHORTEN_BRANCH);
345590282Sobrien#endif
345690282Sobrien
345790282Sobrien  convert_to_eh_region_ranges ();
345890282Sobrien
345918334Speter  /* Shorten branches.  */
346090282Sobrien  timevar_push (TV_SHORTEN_BRANCH);
346190282Sobrien  shorten_branches (get_insns ());
346290282Sobrien  timevar_pop (TV_SHORTEN_BRANCH);
346318334Speter
346490282Sobrien  current_function_nothrow = nothrow_function_p ();
346590282Sobrien  if (current_function_nothrow)
346690282Sobrien    /* Now we know that this can't throw; set the flag for the benefit
346790282Sobrien       of other functions later in this translation unit.  */
346890282Sobrien    TREE_NOTHROW (current_function_decl) = 1;
346952558Sobrien
347090282Sobrien  /* Now turn the rtl into assembler code.  */
347150615Sobrien
347290282Sobrien  timevar_push (TV_FINAL);
347390282Sobrien  {
347490282Sobrien    rtx x;
347590282Sobrien    const char *fnname;
347690282Sobrien
347790282Sobrien    /* Get the function's name, as described by its RTL.  This may be
347890282Sobrien       different from the DECL_NAME name used in the source file.  */
347990282Sobrien
348090282Sobrien    x = DECL_RTL (decl);
348190282Sobrien    if (GET_CODE (x) != MEM)
348290282Sobrien      abort ();
348390282Sobrien    x = XEXP (x, 0);
348490282Sobrien    if (GET_CODE (x) != SYMBOL_REF)
348590282Sobrien      abort ();
348690282Sobrien    fnname = XSTR (x, 0);
348790282Sobrien
348890282Sobrien    assemble_start_function (decl, fnname);
348990282Sobrien    final_start_function (insns, asm_out_file, optimize);
349090282Sobrien    final (insns, asm_out_file, optimize, 0);
349190282Sobrien    final_end_function ();
349290282Sobrien
349390282Sobrien#ifdef IA64_UNWIND_INFO
349490282Sobrien    /* ??? The IA-64 ".handlerdata" directive must be issued before
349590282Sobrien       the ".endp" directive that closes the procedure descriptor.  */
349690282Sobrien    output_function_exception_table ();
349718334Speter#endif
349818334Speter
349990282Sobrien    assemble_end_function (decl, fnname);
350018334Speter
350190282Sobrien#ifndef IA64_UNWIND_INFO
350290282Sobrien    /* Otherwise, it feels unclean to switch sections in the middle.  */
350390282Sobrien    output_function_exception_table ();
350490282Sobrien#endif
350518334Speter
350690282Sobrien    if (! quiet_flag)
350790282Sobrien      fflush (asm_out_file);
350818334Speter
350990282Sobrien    /* Release all memory allocated by flow.  */
351090282Sobrien    free_basic_block_vars (0);
351118334Speter
351290282Sobrien    /* Release all memory held by regsets now.  */
351390282Sobrien    regset_release_memory ();
351490282Sobrien  }
351590282Sobrien  timevar_pop (TV_FINAL);
351650615Sobrien
351790282Sobrien  ggc_collect ();
351852558Sobrien
351990282Sobrien  /* Write DBX symbols if requested.  */
352018334Speter
352118334Speter  /* Note that for those inline functions where we don't initially
352218334Speter     know for certain that we will be generating an out-of-line copy,
352318334Speter     the first invocation of this routine (rest_of_compilation) will
352418334Speter     skip over this code by doing a `goto exit_rest_of_compilation;'.
352518334Speter     Later on, finish_compilation will call rest_of_compilation again
352618334Speter     for those inline functions that need to have out-of-line copies
352718334Speter     generated.  During that call, we *will* be routed past here.  */
352818334Speter
352990282Sobrien  timevar_push (TV_SYMOUT);
353090282Sobrien  (*debug_hooks->function_decl) (decl);
353190282Sobrien  timevar_pop (TV_SYMOUT);
353218334Speter
353318334Speter exit_rest_of_compilation:
353418334Speter
353518334Speter  /* In case the function was not output,
353618334Speter     don't leave any temporary anonymous types
353718334Speter     queued up for sdb output.  */
353818334Speter#ifdef SDB_DEBUGGING_INFO
353918334Speter  if (write_symbols == SDB_DEBUG)
354018334Speter    sdbout_types (NULL_TREE);
354118334Speter#endif
354218334Speter
354318334Speter  reload_completed = 0;
354452558Sobrien  flow2_completed = 0;
354552558Sobrien  no_new_pseudos = 0;
354618334Speter
354790282Sobrien  timevar_push (TV_FINAL);
354818334Speter
354990282Sobrien  /* Clear out the insn_length contents now that they are no
355090282Sobrien     longer valid.  */
355190282Sobrien  init_insn_lengths ();
355218334Speter
355390282Sobrien  /* Clear out the real_constant_chain before some of the rtx's
355490282Sobrien     it runs through become garbage.  */
355590282Sobrien  clear_const_double_mem ();
355618334Speter
355790282Sobrien  /* Show no temporary slots allocated.  */
355890282Sobrien  init_temp_slots ();
355918334Speter
356090282Sobrien  free_basic_block_vars (0);
356190282Sobrien  free_bb_for_insn ();
356290282Sobrien
356390282Sobrien  timevar_pop (TV_FINAL);
356490282Sobrien
356550615Sobrien  /* Make sure volatile mem refs aren't considered valid operands for
356650615Sobrien     arithmetic insns.  We must call this here if this is a nested inline
356750615Sobrien     function, since the above code leaves us in the init_recog state
356850615Sobrien     (from final.c), and the function context push/pop code does not
356950615Sobrien     save/restore volatile_ok.
357018334Speter
357150615Sobrien     ??? Maybe it isn't necessary for expand_start_function to call this
357250615Sobrien     anymore if we do it here?  */
357350615Sobrien
357450615Sobrien  init_recog_no_volatile ();
357550615Sobrien
357690282Sobrien  /* We're done with this function.  Free up memory if we can.  */
357790282Sobrien  free_after_parsing (cfun);
357890282Sobrien  if (! DECL_DEFER_OUTPUT (decl))
357990282Sobrien    {
358090282Sobrien      free_after_compilation (cfun);
358118334Speter
358290282Sobrien      /* Clear integrate.c's pointer to the cfun structure we just
358390282Sobrien	 destroyed.  */
358490282Sobrien      DECL_SAVED_INSNS (decl) = 0;
358590282Sobrien    }
358690282Sobrien  cfun = 0;
358752558Sobrien
358890282Sobrien  ggc_collect ();
358990282Sobrien
359090282Sobrien  timevar_pop (TV_REST_OF_COMPILATION);
359118334Speter}
359218334Speter
359350615Sobrienstatic void
359450615Sobriendisplay_help ()
359550615Sobrien{
359690282Sobrien  int undoc;
359790282Sobrien  unsigned long i;
359890282Sobrien  const char *lang;
359950615Sobrien
360090282Sobrien  printf (_("  -ffixed-<register>      Mark <register> as being unavailable to the compiler\n"));
360190282Sobrien  printf (_("  -fcall-used-<register>  Mark <register> as being corrupted by function calls\n"));
360290282Sobrien  printf (_("  -fcall-saved-<register> Mark <register> as being preserved across functions\n"));
360390282Sobrien  printf (_("  -finline-limit=<number> Limits the size of inlined functions to <number>\n"));
360490282Sobrien  printf (_("  -fmessage-length=<number> Limits diagnostics messages lengths to <number> characters per line.  0 suppresses line-wrapping\n"));
360590282Sobrien  printf (_("  -fdiagnostics-show-location=[once | every-line] Indicates how often source location information should be emitted, as prefix, at the beginning of diagnostics when line-wrapping\n"));
360690282Sobrien
360790282Sobrien  for (i = ARRAY_SIZE (f_options); i--;)
360850615Sobrien    {
360990282Sobrien      const char *description = f_options[i].description;
361090282Sobrien
361150615Sobrien      if (description != NULL && * description != 0)
361250615Sobrien	printf ("  -f%-21s %s\n",
361390282Sobrien		f_options[i].string, _(description));
361450615Sobrien    }
361590282Sobrien
361690282Sobrien  printf (_("  -O[number]              Set optimization level to [number]\n"));
361790282Sobrien  printf (_("  -Os                     Optimize for space rather than speed\n"));
361890282Sobrien  for (i = LAST_PARAM; i--;)
361950615Sobrien    {
362090282Sobrien      const char *description = compiler_params[i].help;
362190282Sobrien      const int length = 21-strlen(compiler_params[i].option);
362290282Sobrien
362350615Sobrien      if (description != NULL && * description != 0)
362490282Sobrien	printf ("  --param %s=<value>%.*s%s\n",
362590282Sobrien		compiler_params[i].option,
362690282Sobrien		length > 0 ? length : 1, "                     ",
362790282Sobrien		_(description));
362890282Sobrien    }
362990282Sobrien  printf (_("  -pedantic               Issue warnings needed by strict compliance to ISO C\n"));
363090282Sobrien  printf (_("  -pedantic-errors        Like -pedantic except that errors are produced\n"));
363190282Sobrien  printf (_("  -w                      Suppress warnings\n"));
363290282Sobrien  printf (_("  -W                      Enable extra warnings\n"));
363390282Sobrien
363490282Sobrien  for (i = ARRAY_SIZE (W_options); i--;)
363590282Sobrien    {
363690282Sobrien      const char *description = W_options[i].description;
363790282Sobrien
363890282Sobrien      if (description != NULL && * description != 0)
363950615Sobrien	printf ("  -W%-21s %s\n",
364090282Sobrien		W_options[i].string, _(description));
364150615Sobrien    }
364290282Sobrien
364390282Sobrien  printf (_("  -Wunused                Enable unused warnings\n"));
364490282Sobrien  printf (_("  -Wlarger-than-<number>  Warn if an object is larger than <number> bytes\n"));
364590282Sobrien  printf (_("  -p                      Enable function profiling\n"));
364650615Sobrien#if defined (BLOCK_PROFILER) || defined (FUNCTION_BLOCK_PROFILER)
364790282Sobrien  printf (_("  -a                      Enable block profiling \n"));
364890282Sobrien#endif
364950615Sobrien#if defined (BLOCK_PROFILER) || defined (FUNCTION_BLOCK_PROFILER) || defined FUNCTION_BLOCK_PROFILER_EXIT
365090282Sobrien  printf (_("  -ax                     Enable jump profiling \n"));
365190282Sobrien#endif
365290282Sobrien  printf (_("  -o <file>               Place output into <file> \n"));
365390282Sobrien  printf (_("\
365490282Sobrien  -G <number>             Put global and static data smaller than <number>\n\
365590282Sobrien                          bytes into a special section (on some targets)\n"));
365690282Sobrien
365790282Sobrien  for (i = ARRAY_SIZE (debug_args); i--;)
365850615Sobrien    {
365950615Sobrien      if (debug_args[i].description != NULL)
366090282Sobrien	printf ("  -g%-21s %s\n",
366190282Sobrien		debug_args[i].arg, _(debug_args[i].description));
366250615Sobrien    }
366390282Sobrien
366490282Sobrien  printf (_("  -aux-info <file>        Emit declaration info into <file>\n"));
366590282Sobrien  printf (_("  -quiet                  Do not display functions compiled or elapsed time\n"));
366690282Sobrien  printf (_("  -version                Display the compiler's version\n"));
366790282Sobrien  printf (_("  -d[letters]             Enable dumps from specific passes of the compiler\n"));
366890282Sobrien  printf (_("  -dumpbase <file>        Base name to be used for dumps from specific passes\n"));
366990282Sobrien#if defined INSN_SCHEDULING
367090282Sobrien  printf (_("  -fsched-verbose=<number> Set the verbosity level of the scheduler\n"));
367150615Sobrien#endif
367290282Sobrien  printf (_("  --help                  Display this information\n"));
367350615Sobrien
367450615Sobrien  undoc = 0;
367550615Sobrien  lang  = "language";
367690282Sobrien
367750615Sobrien  /* Display descriptions of language specific options.
367850615Sobrien     If there is no description, note that there is an undocumented option.
367950615Sobrien     If the description is empty, do not display anything.  (This allows
368050615Sobrien     options to be deliberately undocumented, for whatever reason).
368150615Sobrien     If the option string is missing, then this is a marker, indicating
368252558Sobrien     that the description string is in fact the name of a language, whose
368350615Sobrien     language specific options are to follow.  */
368490282Sobrien
368590282Sobrien  if (ARRAY_SIZE (documented_lang_options) > 1)
368650615Sobrien    {
368790282Sobrien      printf (_("\nLanguage specific options:\n"));
368850615Sobrien
368990282Sobrien      for (i = 0; i < ARRAY_SIZE (documented_lang_options); i++)
369050615Sobrien	{
369190282Sobrien	  const char *description = documented_lang_options[i].description;
369290282Sobrien	  const char *option      = documented_lang_options[i].option;
369350615Sobrien
369450615Sobrien	  if (description == NULL)
369552558Sobrien	    {
369652558Sobrien	      undoc = 1;
369752558Sobrien
369852558Sobrien	      if (extra_warnings)
369990282Sobrien		printf (_("  %-23.23s [undocumented]\n"), option);
370052558Sobrien	    }
370190282Sobrien	  else if (*description == 0)
370250615Sobrien	    continue;
370350615Sobrien	  else if (option == NULL)
370450615Sobrien	    {
370550615Sobrien	      if (undoc)
370650615Sobrien		printf
370790282Sobrien		  (_("\nThere are undocumented %s specific options as well.\n"),
370850615Sobrien			lang);
370950615Sobrien	      undoc = 0;
371050615Sobrien
371190282Sobrien	      printf (_("\n Options for %s:\n"), description);
371290282Sobrien
371350615Sobrien	      lang = description;
371450615Sobrien	    }
371550615Sobrien	  else
371690282Sobrien	    printf ("  %-23.23s %s\n", option, _(description));
371750615Sobrien	}
371850615Sobrien    }
371950615Sobrien
372050615Sobrien  if (undoc)
372190282Sobrien    printf (_("\nThere are undocumented %s specific options as well.\n"),
372290282Sobrien	    lang);
372350615Sobrien
372490282Sobrien  display_target_options ();
372590282Sobrien}
372690282Sobrien
372790282Sobrienstatic void
372890282Sobriendisplay_target_options ()
372990282Sobrien{
373090282Sobrien  int undoc, i;
373190282Sobrien  static bool displayed = false;
373290282Sobrien
373390282Sobrien  /* Avoid double printing for --help --target-help.  */
373490282Sobrien  if (displayed)
373590282Sobrien    return;
373690282Sobrien  displayed = true;
373790282Sobrien
373890282Sobrien  if (ARRAY_SIZE (target_switches) > 1
373950615Sobrien#ifdef TARGET_OPTIONS
374090282Sobrien      || ARRAY_SIZE (target_options) > 1
374150615Sobrien#endif
374250615Sobrien      )
374350615Sobrien    {
374450615Sobrien      int doc = 0;
374590282Sobrien
374650615Sobrien      undoc = 0;
374750615Sobrien
374890282Sobrien      printf (_("\nTarget specific options:\n"));
374990282Sobrien
375090282Sobrien      for (i = ARRAY_SIZE (target_switches); i--;)
375150615Sobrien	{
375290282Sobrien	  const char *option      = target_switches[i].name;
375390282Sobrien	  const char *description = target_switches[i].description;
375450615Sobrien
375590282Sobrien	  if (option == NULL || *option == 0)
375650615Sobrien	    continue;
375750615Sobrien	  else if (description == NULL)
375852558Sobrien	    {
375952558Sobrien	      undoc = 1;
376090282Sobrien
376152558Sobrien	      if (extra_warnings)
376290282Sobrien		printf (_("  -m%-23.23s [undocumented]\n"), option);
376352558Sobrien	    }
376450615Sobrien	  else if (* description != 0)
376590282Sobrien	    doc += printf ("  -m%-23.23s %s\n", option, _(description));
376650615Sobrien	}
376790282Sobrien
376890282Sobrien#ifdef TARGET_OPTIONS
376990282Sobrien      for (i = ARRAY_SIZE (target_options); i--;)
377050615Sobrien	{
377190282Sobrien	  const char *option      = target_options[i].prefix;
377290282Sobrien	  const char *description = target_options[i].description;
377350615Sobrien
377490282Sobrien	  if (option == NULL || *option == 0)
377550615Sobrien	    continue;
377650615Sobrien	  else if (description == NULL)
377752558Sobrien	    {
377852558Sobrien	      undoc = 1;
377990282Sobrien
378052558Sobrien	      if (extra_warnings)
378190282Sobrien		printf (_("  -m%-23.23s [undocumented]\n"), option);
378252558Sobrien	    }
378350615Sobrien	  else if (* description != 0)
378490282Sobrien	    doc += printf ("  -m%-23.23s %s\n", option, _(description));
378550615Sobrien	}
378650615Sobrien#endif
378750615Sobrien      if (undoc)
378852558Sobrien	{
378952558Sobrien	  if (doc)
379090282Sobrien	    printf (_("\nThere are undocumented target specific options as well.\n"));
379152558Sobrien	  else
379290282Sobrien	    printf (_("  They exist, but they are not documented.\n"));
379352558Sobrien	}
379450615Sobrien    }
379550615Sobrien}
379690282Sobrien
379790282Sobrien/* Parse a -d... command line switch.  */
379850615Sobrien
379990282Sobrienstatic void
380090282Sobriendecode_d_option (arg)
380190282Sobrien     const char *arg;
380290282Sobrien{
380390282Sobrien  int i, c, matched;
380450615Sobrien
380590282Sobrien  while (*arg)
380690282Sobrien    switch (c = *arg++)
380790282Sobrien      {
380890282Sobrien      case 'a':
380990282Sobrien	for (i = 0; i < (int) DFI_MAX; ++i)
381090282Sobrien	  dump_file[i].enabled = 1;
381190282Sobrien	break;
381290282Sobrien      case 'A':
381390282Sobrien	flag_debug_asm = 1;
381490282Sobrien	break;
381590282Sobrien      case 'p':
381690282Sobrien	flag_print_asm_name = 1;
381790282Sobrien	break;
381890282Sobrien      case 'P':
381990282Sobrien        flag_dump_rtl_in_asm = 1;
382090282Sobrien        flag_print_asm_name = 1;
382190282Sobrien        break;
382290282Sobrien      case 'v':
382390282Sobrien	graph_dump_format = vcg;
382490282Sobrien	break;
382590282Sobrien      case 'x':
382690282Sobrien	rtl_dump_and_exit = 1;
382790282Sobrien	break;
382890282Sobrien      case 'y':
382990282Sobrien	(*lang_hooks.set_yydebug) (1);
383090282Sobrien	break;
383190282Sobrien      case 'D':	/* These are handled by the preprocessor.  */
383290282Sobrien      case 'I':
383390282Sobrien	break;
383490282Sobrien
383590282Sobrien      default:
383690282Sobrien	matched = 0;
383790282Sobrien	for (i = 0; i < (int) DFI_MAX; ++i)
383890282Sobrien	  if (c == dump_file[i].debug_switch)
383990282Sobrien	    {
384090282Sobrien	      dump_file[i].enabled = 1;
384190282Sobrien	      matched = 1;
384290282Sobrien	    }
384390282Sobrien
384490282Sobrien	if (! matched)
384590282Sobrien	  warning ("unrecognized gcc debugging option: %c", c);
384690282Sobrien	break;
384790282Sobrien      }
384890282Sobrien}
384990282Sobrien
385090282Sobrien/* Parse a -f... command line switch.  ARG is the value after the -f.
385190282Sobrien   It is safe to access 'ARG - 2' to generate the full switch name.
385290282Sobrien   Return the number of strings consumed.  */
385390282Sobrien
385450615Sobrienstatic int
385590282Sobriendecode_f_option (arg)
385690282Sobrien     const char *arg;
385750615Sobrien{
385890282Sobrien  int j;
385990282Sobrien  const char *option_value = NULL;
386050615Sobrien
386190282Sobrien  /* Search for the option in the table of binary f options.  */
386290282Sobrien  for (j = ARRAY_SIZE (f_options); j--;)
386350615Sobrien    {
386490282Sobrien      if (!strcmp (arg, f_options[j].string))
386550615Sobrien	{
386690282Sobrien	  *f_options[j].variable = f_options[j].on_value;
386790282Sobrien	  return 1;
386850615Sobrien	}
386990282Sobrien
387090282Sobrien      if (arg[0] == 'n' && arg[1] == 'o' && arg[2] == '-'
387190282Sobrien	  && ! strcmp (arg + 3, f_options[j].string))
387290282Sobrien	{
387390282Sobrien	  *f_options[j].variable = ! f_options[j].on_value;
387490282Sobrien	  return 1;
387590282Sobrien	}
387650615Sobrien    }
387718334Speter
387890282Sobrien  if (!strcmp (arg, "fast-math"))
387990282Sobrien    set_fast_math_flags ();
388090282Sobrien  else if (!strcmp (arg, "no-fast-math"))
388190282Sobrien    set_no_fast_math_flags ();
388290282Sobrien  else if ((option_value = skip_leading_substring (arg, "inline-limit-"))
388390282Sobrien	   || (option_value = skip_leading_substring (arg, "inline-limit=")))
388490282Sobrien    {
388590282Sobrien      int val =
388690282Sobrien	read_integral_parameter (option_value, arg - 2,
388790282Sobrien				 MAX_INLINE_INSNS);
388890282Sobrien      set_param_value ("max-inline-insns", val);
388990282Sobrien    }
389090282Sobrien#ifdef INSN_SCHEDULING
389190282Sobrien  else if ((option_value = skip_leading_substring (arg, "sched-verbose=")))
389290282Sobrien    fix_sched_param ("verbose", option_value);
389318334Speter#endif
389490282Sobrien  else if ((option_value = skip_leading_substring (arg, "fixed-")))
389590282Sobrien    fix_register (option_value, 1, 1);
389690282Sobrien  else if ((option_value = skip_leading_substring (arg, "call-used-")))
389790282Sobrien    fix_register (option_value, 0, 1);
389890282Sobrien  else if ((option_value = skip_leading_substring (arg, "call-saved-")))
389990282Sobrien    fix_register (option_value, 0, 0);
390090282Sobrien  else if ((option_value = skip_leading_substring (arg, "align-loops=")))
390190282Sobrien    align_loops = read_integral_parameter (option_value, arg - 2, align_loops);
390290282Sobrien  else if ((option_value = skip_leading_substring (arg, "align-functions=")))
390390282Sobrien    align_functions
390490282Sobrien      = read_integral_parameter (option_value, arg - 2, align_functions);
390590282Sobrien  else if ((option_value = skip_leading_substring (arg, "align-jumps=")))
390690282Sobrien    align_jumps = read_integral_parameter (option_value, arg - 2, align_jumps);
390790282Sobrien  else if ((option_value = skip_leading_substring (arg, "align-labels=")))
390890282Sobrien    align_labels
390990282Sobrien      = read_integral_parameter (option_value, arg - 2, align_labels);
391090282Sobrien  else if ((option_value
391190282Sobrien	    = skip_leading_substring (arg, "stack-limit-register=")))
391290282Sobrien    {
391390282Sobrien      int reg = decode_reg_name (option_value);
391490282Sobrien      if (reg < 0)
391590282Sobrien	error ("unrecognized register name `%s'", option_value);
391690282Sobrien      else
391790282Sobrien	stack_limit_rtx = gen_rtx_REG (Pmode, reg);
391890282Sobrien    }
391990282Sobrien  else if ((option_value
392090282Sobrien	    = skip_leading_substring (arg, "stack-limit-symbol=")))
392190282Sobrien    {
392290282Sobrien      const char *nm;
392390282Sobrien      nm = ggc_strdup (option_value);
392490282Sobrien      stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, nm);
392590282Sobrien    }
392690282Sobrien  else if ((option_value
392790282Sobrien            = skip_leading_substring (arg, "message-length=")))
392890282Sobrien    output_set_maximum_length
392990282Sobrien      (&global_dc->buffer, read_integral_parameter
393090282Sobrien       (option_value, arg - 2, diagnostic_line_cutoff (global_dc)));
393190282Sobrien  else if ((option_value
393290282Sobrien	    = skip_leading_substring (arg, "diagnostics-show-location=")))
393390282Sobrien    {
393490282Sobrien      if (!strcmp (option_value, "once"))
393590282Sobrien        diagnostic_prefixing_rule (global_dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
393690282Sobrien      else if (!strcmp (option_value, "every-line"))
393790282Sobrien        diagnostic_prefixing_rule (global_dc)
393890282Sobrien          = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
393990282Sobrien      else
394090282Sobrien	error ("unrecognized option `%s'", arg - 2);
394190282Sobrien    }
394290282Sobrien  else if (!strcmp (arg, "no-stack-limit"))
394390282Sobrien    stack_limit_rtx = NULL_RTX;
394490282Sobrien  else if (!strcmp (arg, "preprocessed"))
394590282Sobrien    /* Recognise this switch but do nothing.  This prevents warnings
394690282Sobrien       about an unrecognized switch if cpplib has not been linked in.  */
394790282Sobrien    ;
394890282Sobrien  else
394990282Sobrien    return 0;
395018334Speter
395190282Sobrien  return 1;
395290282Sobrien}
395318334Speter
395490282Sobrien/* Parse a -W... command line switch.  ARG is the value after the -W.
395590282Sobrien   It is safe to access 'ARG - 2' to generate the full switch name.
395690282Sobrien   Return the number of strings consumed.  */
395718334Speter
395890282Sobrienstatic int
395990282Sobriendecode_W_option (arg)
396090282Sobrien     const char *arg;
396190282Sobrien{
396290282Sobrien  const char *option_value = NULL;
396390282Sobrien  int j;
396452558Sobrien
396590282Sobrien  /* Search for the option in the table of binary W options.  */
396618334Speter
396790282Sobrien  for (j = ARRAY_SIZE (W_options); j--;)
396818334Speter    {
396990282Sobrien      if (!strcmp (arg, W_options[j].string))
397018334Speter	{
397190282Sobrien	  *W_options[j].variable = W_options[j].on_value;
397290282Sobrien	  return 1;
397318334Speter	}
397490282Sobrien
397590282Sobrien      if (arg[0] == 'n' && arg[1] == 'o' && arg[2] == '-'
397690282Sobrien	  && ! strcmp (arg + 3, W_options[j].string))
397718334Speter	{
397890282Sobrien	  *W_options[j].variable = ! W_options[j].on_value;
397990282Sobrien	  return 1;
398018334Speter	}
398118334Speter    }
398218334Speter
398390282Sobrien  if ((option_value = skip_leading_substring (arg, "id-clash-")))
398490282Sobrien    warning ("-Wid-clash-LEN is no longer supported");
398590282Sobrien  else if ((option_value = skip_leading_substring (arg, "larger-than-")))
398690282Sobrien    {
398790282Sobrien      larger_than_size = read_integral_parameter (option_value, arg - 2, -1);
398818334Speter
398990282Sobrien      warn_larger_than = larger_than_size != -1;
399018334Speter    }
399190282Sobrien  else if (!strcmp (arg, "unused"))
399218334Speter    {
399390282Sobrien      set_Wunused (1);
399418334Speter    }
399590282Sobrien  else if (!strcmp (arg, "no-unused"))
399618334Speter    {
399790282Sobrien      set_Wunused (0);
399818334Speter    }
399990282Sobrien  else
400090282Sobrien    return 0;
400118334Speter
400290282Sobrien  return 1;
400390282Sobrien}
400450615Sobrien
400590282Sobrien/* Parse a -g... command line switch.  ARG is the value after the -g.
400690282Sobrien   It is safe to access 'ARG - 2' to generate the full switch name.
400790282Sobrien   Return the number of strings consumed.  */
400818334Speter
400990282Sobrienstatic int
401090282Sobriendecode_g_option (arg)
401190282Sobrien     const char *arg;
401290282Sobrien{
401390282Sobrien  static unsigned level=0;
401490282Sobrien  /* A lot of code assumes write_symbols == NO_DEBUG if the
401590282Sobrien     debugging level is 0 (thus -gstabs1 -gstabs0 would lose track
401690282Sobrien     of what debugging type has been selected).  This records the
401790282Sobrien     selected type.  It is an error to specify more than one
401890282Sobrien     debugging type.  */
401990282Sobrien  static enum debug_info_type selected_debug_type = NO_DEBUG;
402090282Sobrien  /* Non-zero if debugging format has been explicitly set.
402190282Sobrien     -g and -ggdb don't explicitly set the debugging format so
402290282Sobrien     -gdwarf -g3 is equivalent to -gdwarf3.  */
402390282Sobrien  static int type_explicitly_set_p = 0;
402490282Sobrien  /* Indexed by enum debug_info_type.  */
402590282Sobrien  static const char *const debug_type_names[] =
402690282Sobrien  {
402790282Sobrien    "none", "stabs", "coff", "dwarf-1", "dwarf-2", "xcoff", "vms"
402890282Sobrien  };
402918334Speter
403090282Sobrien  /* The maximum admissible debug level value.  */
403190282Sobrien  static const unsigned max_debug_level = 3;
403290282Sobrien
403390282Sobrien  /* Look up ARG in the table.  */
403490282Sobrien  for (da = debug_args; da->arg; da++)
403518334Speter    {
403690282Sobrien      const int da_len = strlen (da->arg);
403790282Sobrien
403890282Sobrien      if (da_len == 0 || ! strncmp (arg, da->arg, da_len))
403950615Sobrien	{
404090282Sobrien	  enum debug_info_type type = da->debug_type;
404190282Sobrien	  const char *p = arg + da_len;
404218334Speter
404390282Sobrien	  if (*p && ! ISDIGIT (*p))
404490282Sobrien	    continue;
404518334Speter
404690282Sobrien	  /* A debug flag without a level defaults to level 2.
404790282Sobrien	     Note we do not want to call read_integral_parameter
404890282Sobrien	     for that case since it will call atoi which
404990282Sobrien	     will return zero.
405018334Speter
405190282Sobrien	     ??? We may want to generalize the interface to
405290282Sobrien	     read_integral_parameter to better handle this case
405390282Sobrien	     if this case shows up often.  */
405490282Sobrien	  if (*p)
405590282Sobrien	    level = read_integral_parameter (p, 0, max_debug_level + 1);
405690282Sobrien	  else
405790282Sobrien	    level = (level == 0) ? 2 : level;
405818334Speter
405990282Sobrien	  if (da_len > 1 && *p && !strncmp (arg, "dwarf", da_len))
406018334Speter	    {
406190282Sobrien	      error ("use -gdwarf -g%d for DWARF v1, level %d",
406290282Sobrien		     level, level);
406390282Sobrien	      if (level == 2)
406490282Sobrien		error ("use -gdwarf-2   for DWARF v2");
406518334Speter	    }
406690282Sobrien
406790282Sobrien	  if (level > max_debug_level)
406818334Speter	    {
406990282Sobrien	      warning ("\
407090282Sobrienignoring option `%s' due to invalid debug level specification",
407190282Sobrien		       arg - 2);
407290282Sobrien	      level = debug_info_level;
407318334Speter	    }
407418334Speter
407590282Sobrien	  if (type == NO_DEBUG)
407618334Speter	    {
407790282Sobrien	      type = PREFERRED_DEBUGGING_TYPE;
407818334Speter
407990282Sobrien	      if (da_len > 1 && strncmp (arg, "gdb", da_len) == 0)
408018334Speter		{
408196289Sobrien#ifdef DWARF2_DEBUGGING_INFO
408290282Sobrien		  type = DWARF2_DEBUG;
408350615Sobrien#else
408418334Speter#ifdef DBX_DEBUGGING_INFO
408590282Sobrien		  type = DBX_DEBUG;
408650615Sobrien#endif
408750615Sobrien#endif
408890282Sobrien		}
408990282Sobrien	    }
409018334Speter
409190282Sobrien	  if (type == NO_DEBUG)
409290282Sobrien	    warning ("`%s': unknown or unsupported -g option", arg - 2);
409318334Speter
409490282Sobrien	  /* Does it conflict with an already selected type?  */
409590282Sobrien	  if (type_explicitly_set_p
409690282Sobrien	      /* -g/-ggdb don't conflict with anything.  */
409790282Sobrien	      && da->debug_type != NO_DEBUG
409890282Sobrien	      && type != selected_debug_type)
409990282Sobrien	    warning ("`%s' ignored, conflicts with `-g%s'",
410090282Sobrien		     arg - 2, debug_type_names[(int) selected_debug_type]);
410190282Sobrien	  else
410218334Speter	    {
410390282Sobrien	      /* If the format has already been set, -g/-ggdb
410490282Sobrien		 only change the debug level.  */
410590282Sobrien	      if (type_explicitly_set_p && da->debug_type == NO_DEBUG)
410690282Sobrien		/* Don't change debugging type.  */
410790282Sobrien		;
410852558Sobrien	      else
410990282Sobrien		{
411090282Sobrien		  selected_debug_type = type;
411190282Sobrien		  type_explicitly_set_p = da->debug_type != NO_DEBUG;
411252558Sobrien		}
411390282Sobrien
411490282Sobrien	      write_symbols = (level == 0
411590282Sobrien			       ? NO_DEBUG
411690282Sobrien			       : selected_debug_type);
411790282Sobrien	      use_gnu_debug_info_extensions = da->use_extensions_p;
411890282Sobrien	      debug_info_level = (enum debug_info_level) level;
411918334Speter	    }
412090282Sobrien
412190282Sobrien	  break;
412218334Speter	}
412318334Speter    }
412418334Speter
412590282Sobrien  if (! da->arg)
412690282Sobrien    return 0;
412718334Speter
412890282Sobrien  return 1;
412990282Sobrien}
413090282Sobrien
413190282Sobrien/* Decode the first argument in the argv as a language-independent option.
413290282Sobrien   Return the number of strings consumed.  */
413390282Sobrien
413490282Sobrienstatic unsigned int
413590282Sobrienindependent_decode_option (argc, argv)
413690282Sobrien     int argc;
413790282Sobrien     char **argv;
413890282Sobrien{
413990282Sobrien  char *arg = argv[0];
414090282Sobrien
414190282Sobrien  if (arg[0] != '-' || arg[1] == 0)
414218334Speter    {
414390282Sobrien      if (arg[0] == '+')
414490282Sobrien	return 0;
414518334Speter
414690282Sobrien      filename = arg;
414790282Sobrien
414890282Sobrien      return 1;
414918334Speter    }
415018334Speter
415190282Sobrien  arg++;
415218334Speter
415390282Sobrien  if (!strcmp (arg, "-help"))
415450615Sobrien    {
415590282Sobrien      display_help ();
415690282Sobrien      exit_after_options = 1;
415750615Sobrien    }
415850615Sobrien
415990282Sobrien  if (!strcmp (arg, "-target-help"))
416050615Sobrien    {
416190282Sobrien      display_target_options ();
416290282Sobrien      exit_after_options = 1;
416350615Sobrien    }
416450615Sobrien
416590282Sobrien  if (!strcmp (arg, "-version"))
416618334Speter    {
416790282Sobrien      print_version (stderr, "");
416890282Sobrien      exit_after_options = 1;
416918334Speter    }
417018334Speter
417190282Sobrien  /* Handle '--param <name>=<value>'.  */
417290282Sobrien  if (strcmp (arg, "-param") == 0)
417390282Sobrien    {
417490282Sobrien      char *equal;
417518334Speter
417690282Sobrien      if (argc == 1)
417752558Sobrien	{
417890282Sobrien	  error ("-param option missing argument");
417990282Sobrien	  return 1;
418052558Sobrien	}
418190282Sobrien
418290282Sobrien      /* Get the '<name>=<value>' parameter.  */
418390282Sobrien      arg = argv[1];
418490282Sobrien      /* Look for the `='.  */
418590282Sobrien      equal = strchr (arg, '=');
418690282Sobrien      if (!equal)
418790282Sobrien	error ("invalid --param option: %s", arg);
418852558Sobrien      else
418990282Sobrien	{
419090282Sobrien	  int val;
419152558Sobrien
419290282Sobrien	  /* Zero out the `=' sign so that we get two separate strings.  */
419390282Sobrien	  *equal = '\0';
419490282Sobrien	  /* Figure out what value is specified.  */
419590282Sobrien	  val = read_integral_parameter (equal + 1, NULL, INVALID_PARAM_VAL);
419690282Sobrien	  if (val != INVALID_PARAM_VAL)
419790282Sobrien	    set_param_value (arg, val);
419890282Sobrien	  else
419990282Sobrien	    error ("invalid parameter value `%s'", equal + 1);
420090282Sobrien	}
420190282Sobrien
420290282Sobrien      return 2;
420318334Speter    }
420418334Speter
420590282Sobrien  if (*arg == 'Y')
420690282Sobrien    arg++;
420718334Speter
420890282Sobrien  switch (*arg)
420918334Speter    {
421090282Sobrien    default:
421190282Sobrien      return 0;
421218334Speter
421390282Sobrien    case 'O':
421490282Sobrien      /* Already been treated in main (). Do nothing.  */
421590282Sobrien      break;
421618334Speter
421790282Sobrien    case 'm':
421890282Sobrien      set_target_switch (arg + 1);
421990282Sobrien      break;
422090282Sobrien
422190282Sobrien    case 'f':
422290282Sobrien      return decode_f_option (arg + 1);
422390282Sobrien
422490282Sobrien    case 'g':
422590282Sobrien      return decode_g_option (arg + 1);
422690282Sobrien
422790282Sobrien    case 'd':
422890282Sobrien      if (!strcmp (arg, "dumpbase"))
422990282Sobrien	{
423090282Sobrien	  if (argc == 1)
423190282Sobrien	    return 0;
423290282Sobrien
423390282Sobrien	  dump_base_name = argv[1];
423490282Sobrien	  return 2;
423590282Sobrien	}
423690282Sobrien      else
423790282Sobrien	decode_d_option (arg + 1);
423890282Sobrien      break;
423990282Sobrien
424090282Sobrien    case 'p':
424190282Sobrien      if (!strcmp (arg, "pedantic"))
424290282Sobrien	pedantic = 1;
424390282Sobrien      else if (!strcmp (arg, "pedantic-errors"))
424490282Sobrien	flag_pedantic_errors = pedantic = 1;
424590282Sobrien      else if (arg[1] == 0)
424690282Sobrien	profile_flag = 1;
424790282Sobrien      else
424890282Sobrien	return 0;
424990282Sobrien      break;
425090282Sobrien
425190282Sobrien    case 'q':
425290282Sobrien      if (!strcmp (arg, "quiet"))
425390282Sobrien	quiet_flag = 1;
425490282Sobrien      else
425590282Sobrien	return 0;
425690282Sobrien      break;
425790282Sobrien
425890282Sobrien    case 'v':
425990282Sobrien      if (!strcmp (arg, "version"))
426090282Sobrien	version_flag = 1;
426190282Sobrien      else
426290282Sobrien	return 0;
426390282Sobrien      break;
426490282Sobrien
426590282Sobrien    case 'w':
426690282Sobrien      if (arg[1] == 0)
426790282Sobrien	inhibit_warnings = 1;
426890282Sobrien      else
426990282Sobrien	return 0;
427090282Sobrien      break;
427190282Sobrien
427290282Sobrien    case 'W':
427390282Sobrien      if (arg[1] == 0)
427490282Sobrien	{
427590282Sobrien	  extra_warnings = 1;
427690282Sobrien	  /* We save the value of warn_uninitialized, since if they put
427790282Sobrien	     -Wuninitialized on the command line, we need to generate a
427890282Sobrien	     warning about not using it without also specifying -O.  */
427990282Sobrien	  if (warn_uninitialized != 1)
428090282Sobrien	    warn_uninitialized = 2;
428190282Sobrien	}
428290282Sobrien      else
428390282Sobrien	return decode_W_option (arg + 1);
428490282Sobrien      break;
428590282Sobrien
428690282Sobrien    case 'a':
428790282Sobrien      if (!strncmp (arg, "aux-info", 8))
428890282Sobrien	{
428990282Sobrien	  if (arg[8] == '\0')
429090282Sobrien	    {
429190282Sobrien	      if (argc == 1)
429290282Sobrien		return 0;
429390282Sobrien
429490282Sobrien	      aux_info_file_name = argv[1];
429590282Sobrien	      flag_gen_aux_info = 1;
429690282Sobrien	      return 2;
429790282Sobrien	    }
429890282Sobrien	  else if (arg[8] == '=')
429990282Sobrien	    {
430090282Sobrien	      aux_info_file_name = arg + 9;
430190282Sobrien	      flag_gen_aux_info = 1;
430290282Sobrien	    }
430390282Sobrien	  else
430490282Sobrien	    return 0;
430590282Sobrien	}
430690282Sobrien      else
430790282Sobrien	return 0;
430890282Sobrien      break;
430990282Sobrien
431090282Sobrien    case 'o':
431190282Sobrien      if (arg[1] == 0)
431290282Sobrien	{
431390282Sobrien	  if (argc == 1)
431490282Sobrien	    return 0;
431590282Sobrien
431690282Sobrien	  asm_file_name = argv[1];
431790282Sobrien	  return 2;
431890282Sobrien	}
431990282Sobrien      return 0;
432090282Sobrien
432190282Sobrien    case 'G':
432290282Sobrien      {
432390282Sobrien	int g_switch_val;
432490282Sobrien	int return_val;
432590282Sobrien
432690282Sobrien	if (arg[1] == 0)
432790282Sobrien	  {
432890282Sobrien	    if (argc == 1)
432990282Sobrien	      return 0;
433090282Sobrien
433190282Sobrien	    g_switch_val = read_integral_parameter (argv[1], 0, -1);
433290282Sobrien	    return_val = 2;
433390282Sobrien	  }
433490282Sobrien	else
433590282Sobrien	  {
433690282Sobrien	    g_switch_val = read_integral_parameter (arg + 1, 0, -1);
433790282Sobrien	    return_val = 1;
433890282Sobrien	  }
433990282Sobrien
434090282Sobrien	if (g_switch_val == -1)
434190282Sobrien	  return_val = 0;
434290282Sobrien	else
434390282Sobrien	  {
434490282Sobrien	    g_switch_set = TRUE;
434590282Sobrien	    g_switch_value = g_switch_val;
434690282Sobrien	  }
434790282Sobrien
434890282Sobrien	return return_val;
434990282Sobrien      }
435018334Speter    }
435118334Speter
435290282Sobrien  return 1;
435318334Speter}
435418334Speter
435518334Speter/* Decode -m switches.  */
435618334Speter/* Decode the switch -mNAME.  */
435718334Speter
435852558Sobrienstatic void
435918334Speterset_target_switch (name)
436090282Sobrien     const char *name;
436118334Speter{
436290282Sobrien  size_t j;
436352558Sobrien  int valid_target_option = 0;
436418334Speter
436590282Sobrien  for (j = 0; j < ARRAY_SIZE (target_switches); j++)
436618334Speter    if (!strcmp (target_switches[j].name, name))
436718334Speter      {
436818334Speter	if (target_switches[j].value < 0)
436918334Speter	  target_flags &= ~-target_switches[j].value;
437018334Speter	else
437118334Speter	  target_flags |= target_switches[j].value;
437252558Sobrien	valid_target_option = 1;
437318334Speter      }
437418334Speter
437518334Speter#ifdef TARGET_OPTIONS
437652558Sobrien  if (!valid_target_option)
437790282Sobrien    for (j = 0; j < ARRAY_SIZE (target_options); j++)
437818334Speter      {
437918334Speter	int len = strlen (target_options[j].prefix);
438018334Speter	if (!strncmp (target_options[j].prefix, name, len))
438118334Speter	  {
438218334Speter	    *target_options[j].variable = name + len;
438352558Sobrien	    valid_target_option = 1;
438418334Speter	  }
438518334Speter      }
438618334Speter#endif
438718334Speter
438852558Sobrien  if (!valid_target_option)
438990282Sobrien    error ("invalid option `%s'", name);
439018334Speter}
439118334Speter
439250615Sobrien/* Print version information to FILE.
439350615Sobrien   Each line begins with INDENT (for the case where FILE is the
439450615Sobrien   assembler output file).  */
439518334Speter
439652558Sobrienstatic void
439750615Sobrienprint_version (file, indent)
439850615Sobrien     FILE *file;
439952558Sobrien     const char *indent;
440050615Sobrien{
440150615Sobrien#ifndef __VERSION__
440252558Sobrien#define __VERSION__ "[?]"
440350615Sobrien#endif
440452558Sobrien  fnotice (file,
440552558Sobrien#ifdef __GNUC__
440690282Sobrien	   "%s%s%s version %s (%s)\n%s\tcompiled by GNU C version %s.\n"
440750615Sobrien#else
440852558Sobrien	   "%s%s%s version %s (%s) compiled by CC.\n"
440950615Sobrien#endif
441052558Sobrien	   , indent, *indent != 0 ? " " : "",
441190282Sobrien	   lang_hooks.name, version_string, TARGET_NAME,
441290282Sobrien	   indent, __VERSION__);
441350615Sobrien}
441418334Speter
441550615Sobrien/* Print an option value and return the adjusted position in the line.
441650615Sobrien   ??? We don't handle error returns from fprintf (disk full); presumably
441750615Sobrien   other code will catch a disk full though.  */
441818334Speter
441952558Sobrienstatic int
442050615Sobrienprint_single_switch (file, pos, max, indent, sep, term, type, name)
442150615Sobrien     FILE *file;
442250615Sobrien     int pos, max;
442352558Sobrien     const char *indent, *sep, *term, *type, *name;
442418334Speter{
442550615Sobrien  /* The ultrix fprintf returns 0 on success, so compute the result we want
442650615Sobrien     here since we need it for the following test.  */
442750615Sobrien  int len = strlen (sep) + strlen (type) + strlen (name);
442818334Speter
442950615Sobrien  if (pos != 0
443050615Sobrien      && pos + len > max)
443118334Speter    {
443250615Sobrien      fprintf (file, "%s", term);
443350615Sobrien      pos = 0;
443418334Speter    }
443550615Sobrien  if (pos == 0)
443650615Sobrien    {
443750615Sobrien      fprintf (file, "%s", indent);
443850615Sobrien      pos = strlen (indent);
443950615Sobrien    }
444050615Sobrien  fprintf (file, "%s%s%s", sep, type, name);
444150615Sobrien  pos += len;
444250615Sobrien  return pos;
444318334Speter}
444490282Sobrien
444550615Sobrien/* Print active target switches to FILE.
444650615Sobrien   POS is the current cursor position and MAX is the size of a "line".
444750615Sobrien   Each line begins with INDENT and ends with TERM.
444850615Sobrien   Each switch is separated from the next by SEP.  */
444918334Speter
445052558Sobrienstatic void
445150615Sobrienprint_switch_values (file, pos, max, indent, sep, term)
445250615Sobrien     FILE *file;
445350615Sobrien     int pos, max;
445452558Sobrien     const char *indent, *sep, *term;
445518334Speter{
445650615Sobrien  size_t j;
445750615Sobrien  char **p;
445818334Speter
445950615Sobrien  /* Print the options as passed.  */
446018334Speter
446150615Sobrien  pos = print_single_switch (file, pos, max, indent, *indent ? " " : "", term,
446252558Sobrien			     _("options passed: "), "");
446350615Sobrien
446450615Sobrien  for (p = &save_argv[1]; *p != NULL; p++)
446550615Sobrien    if (**p == '-')
446650615Sobrien      {
446750615Sobrien	/* Ignore these.  */
446850615Sobrien	if (strcmp (*p, "-o") == 0)
446950615Sobrien	  {
447050615Sobrien	    if (p[1] != NULL)
447150615Sobrien	      p++;
447250615Sobrien	    continue;
447350615Sobrien	  }
447450615Sobrien	if (strcmp (*p, "-quiet") == 0)
447550615Sobrien	  continue;
447650615Sobrien	if (strcmp (*p, "-version") == 0)
447750615Sobrien	  continue;
447850615Sobrien	if ((*p)[1] == 'd')
447950615Sobrien	  continue;
448050615Sobrien
448150615Sobrien	pos = print_single_switch (file, pos, max, indent, sep, term, *p, "");
448250615Sobrien      }
448350615Sobrien  if (pos > 0)
448450615Sobrien    fprintf (file, "%s", term);
448550615Sobrien
448650615Sobrien  /* Print the -f and -m options that have been enabled.
448750615Sobrien     We don't handle language specific options but printing argv
448850615Sobrien     should suffice.  */
448950615Sobrien
449050615Sobrien  pos = print_single_switch (file, 0, max, indent, *indent ? " " : "", term,
449152558Sobrien			     _("options enabled: "), "");
449250615Sobrien
449390282Sobrien  for (j = 0; j < ARRAY_SIZE (f_options); j++)
449418334Speter    if (*f_options[j].variable == f_options[j].on_value)
449550615Sobrien      pos = print_single_switch (file, pos, max, indent, sep, term,
449650615Sobrien				 "-f", f_options[j].string);
449718334Speter
449850615Sobrien  /* Print target specific options.  */
449918334Speter
450090282Sobrien  for (j = 0; j < ARRAY_SIZE (target_switches); j++)
450118334Speter    if (target_switches[j].name[0] != '\0'
450218334Speter	&& target_switches[j].value > 0
450318334Speter	&& ((target_switches[j].value & target_flags)
450418334Speter	    == target_switches[j].value))
450550615Sobrien      {
450650615Sobrien	pos = print_single_switch (file, pos, max, indent, sep, term,
450750615Sobrien				   "-m", target_switches[j].name);
450850615Sobrien      }
450918334Speter
451050615Sobrien#ifdef TARGET_OPTIONS
451190282Sobrien  for (j = 0; j < ARRAY_SIZE (target_options); j++)
451250615Sobrien    if (*target_options[j].variable != NULL)
451350615Sobrien      {
451450615Sobrien	char prefix[256];
451550615Sobrien	sprintf (prefix, "-m%s", target_options[j].prefix);
451650615Sobrien	pos = print_single_switch (file, pos, max, indent, sep, term,
451750615Sobrien				   prefix, *target_options[j].variable);
451850615Sobrien      }
451950615Sobrien#endif
452050615Sobrien
452150615Sobrien  fprintf (file, "%s", term);
452218334Speter}
452390282Sobrien
452490282Sobrien/* Open assembly code output file.  Do this even if -fsyntax-only is
452590282Sobrien   on, because then the driver will have provided the name of a
452690282Sobrien   temporary file or bit bucket for us.  NAME is the file specified on
452790282Sobrien   the command line, possibly NULL.  */
452890282Sobrienstatic void
452990282Sobrieninit_asm_output (name)
453090282Sobrien     const char *name;
453190282Sobrien{
453290282Sobrien  if (name == NULL && asm_file_name == 0)
453390282Sobrien    asm_out_file = stdout;
453490282Sobrien  else
453590282Sobrien    {
453690282Sobrien      if (asm_file_name == 0)
453790282Sobrien        {
453890282Sobrien          int len = strlen (dump_base_name);
453990282Sobrien          char *dumpname = (char *) xmalloc (len + 6);
454090282Sobrien          memcpy (dumpname, dump_base_name, len + 1);
454190282Sobrien          strip_off_ending (dumpname, len);
454290282Sobrien          strcat (dumpname, ".s");
454390282Sobrien          asm_file_name = dumpname;
454490282Sobrien        }
454590282Sobrien      if (!strcmp (asm_file_name, "-"))
454690282Sobrien        asm_out_file = stdout;
454790282Sobrien      else
454890282Sobrien        asm_out_file = fopen (asm_file_name, "w");
454990282Sobrien      if (asm_out_file == 0)
455090282Sobrien	fatal_io_error ("can't open %s for writing", asm_file_name);
455190282Sobrien    }
455250615Sobrien
455390282Sobrien#ifdef IO_BUFFER_SIZE
455490282Sobrien  setvbuf (asm_out_file, (char *) xmalloc (IO_BUFFER_SIZE),
455590282Sobrien           _IOFBF, IO_BUFFER_SIZE);
455690282Sobrien#endif
455750615Sobrien
455890282Sobrien  if (!flag_syntax_only)
455990282Sobrien    {
456090282Sobrien#ifdef ASM_FILE_START
456190282Sobrien      ASM_FILE_START (asm_out_file);
456290282Sobrien#endif
456390282Sobrien
456490282Sobrien#ifdef ASM_COMMENT_START
456590282Sobrien      if (flag_verbose_asm)
456690282Sobrien	{
456790282Sobrien	  /* Print the list of options in effect.  */
456890282Sobrien	  print_version (asm_out_file, ASM_COMMENT_START);
456990282Sobrien	  print_switch_values (asm_out_file, 0, MAX_LINE,
457090282Sobrien			       ASM_COMMENT_START, " ", "\n");
457190282Sobrien	  /* Add a blank line here so it appears in assembler output but not
457290282Sobrien	     screen output.  */
457390282Sobrien	  fprintf (asm_out_file, "\n");
457490282Sobrien	}
457590282Sobrien#endif
457690282Sobrien    }
457790282Sobrien}
457890282Sobrien
457990282Sobrien/* Initialization of the front end environment, before command line
458090282Sobrien   options are parsed.  Signal handlers, internationalization etc.
458190282Sobrien   ARGV0 is main's argv[0].  */
458290282Sobrienstatic void
458390282Sobriengeneral_init (argv0)
458490282Sobrien     char *argv0;
458550615Sobrien{
458690282Sobrien  char *p;
458790282Sobrien
458890282Sobrien  p = argv0 + strlen (argv0);
458990282Sobrien  while (p != argv0 && !IS_DIR_SEPARATOR (p[-1]))
459090282Sobrien    --p;
459190282Sobrien  progname = p;
459290282Sobrien
459390282Sobrien  xmalloc_set_program_name (progname);
459490282Sobrien
459590282Sobrien  gcc_init_libintl ();
459690282Sobrien
459790282Sobrien  /* Install handler for SIGFPE, which may be received while we do
459890282Sobrien     compile-time floating point arithmetic.  */
459990282Sobrien  signal (SIGFPE, float_signal);
460090282Sobrien
460190282Sobrien  /* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages.  */
460290282Sobrien#ifdef SIGSEGV
460390282Sobrien  signal (SIGSEGV, crash_signal);
460450615Sobrien#endif
460590282Sobrien#ifdef SIGILL
460690282Sobrien  signal (SIGILL, crash_signal);
460750615Sobrien#endif
460890282Sobrien#ifdef SIGBUS
460990282Sobrien  signal (SIGBUS, crash_signal);
461090282Sobrien#endif
461190282Sobrien#ifdef SIGABRT
461290282Sobrien  signal (SIGABRT, crash_signal);
461390282Sobrien#endif
461490282Sobrien#if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT)
461590282Sobrien  signal (SIGIOT, crash_signal);
461690282Sobrien#endif
461790282Sobrien
461890282Sobrien  /* Initialize the diagnostics reporting machinery, so option parsing
461990282Sobrien     can give warnings and errors.  */
462090282Sobrien  diagnostic_initialize (global_dc);
462150615Sobrien}
462290282Sobrien
462390282Sobrien/* Parse command line options and set default flag values, called
462490282Sobrien   after language-independent option-independent initialization.  Do
462590282Sobrien   minimal options processing.  Outputting diagnostics is OK, but GC
462690282Sobrien   and identifier hashtables etc. are not initialized yet.  */
462790282Sobrienstatic void
462890282Sobrienparse_options_and_default_flags (argc, argv)
462990282Sobrien     int argc;
463090282Sobrien     char **argv;
463190282Sobrien{
463290282Sobrien  int i;
463350615Sobrien
463490282Sobrien  /* Save in case md file wants to emit args as a comment.  */
463590282Sobrien  save_argc = argc;
463690282Sobrien  save_argv = argv;
463750615Sobrien
463890282Sobrien  /* Initialize register usage now so switches may override.  */
463990282Sobrien  init_reg_sets ();
464090282Sobrien
464190282Sobrien  /* Register the language-independent parameters.  */
464290282Sobrien  add_params (lang_independent_params, LAST_PARAM);
464390282Sobrien
464490282Sobrien  /* Perform language-specific options initialization.  */
464590282Sobrien  (*lang_hooks.init_options) ();
464690282Sobrien
464790282Sobrien  /* Scan to see what optimization level has been specified.  That will
464890282Sobrien     determine the default value of many flags.  */
464990282Sobrien  for (i = 1; i < argc; i++)
465090282Sobrien    {
465190282Sobrien      if (!strcmp (argv[i], "-O"))
465290282Sobrien	{
465390282Sobrien	  optimize = 1;
465490282Sobrien	  optimize_size = 0;
465590282Sobrien	}
465690282Sobrien      else if (argv[i][0] == '-' && argv[i][1] == 'O')
465790282Sobrien	{
465890282Sobrien	  /* Handle -Os, -O2, -O3, -O69, ...  */
465990282Sobrien	  char *p = &argv[i][2];
466090282Sobrien
466190282Sobrien	  if ((p[0] == 's') && (p[1] == 0))
466290282Sobrien	    {
466390282Sobrien	      optimize_size = 1;
466490282Sobrien
466590282Sobrien	      /* Optimizing for size forces optimize to be 2.  */
466690282Sobrien	      optimize = 2;
466790282Sobrien	    }
466890282Sobrien	  else
466990282Sobrien	    {
467090282Sobrien	      const int optimize_val = read_integral_parameter (p, p - 2, -1);
467190282Sobrien	      if (optimize_val != -1)
467290282Sobrien		{
467390282Sobrien		  optimize = optimize_val;
467490282Sobrien
467590282Sobrien#ifdef FORCE_OPTIMIZATION_DOWNGRADE
467690282Sobrien#warning FORCE_OPTIMIZATION_DOWNGRADE
467790282Sobrien		  if (optimize > FORCE_OPTIMIZATION_DOWNGRADE)
467890282Sobrien		    {
467990282Sobrien		      optimize = FORCE_OPTIMIZATION_DOWNGRADE;
468096289Sobrien		      warning ("\n***\n***\t-O%d converted to \"-O%d\" due to optimizer bugs on this platform\n***",
468190282Sobrien			      optimize_val,
468290282Sobrien			      FORCE_OPTIMIZATION_DOWNGRADE);
468390282Sobrien
468490282Sobrien		    }
468590282Sobrien#endif /*FORCE_OPTIMIZATION_DOWNGRADE*/
468690282Sobrien
468790282Sobrien#if defined(__alpha__)
468890282Sobrien		  if (optimize > 1)
468990282Sobrien		    {
469096289Sobrien		      warning ("\n***\n***\tThe -O%d flag TRIGGERS KNOWN OPTIMIZER BUGS ON THIS PLATFORM\n***",
469190282Sobrien			      optimize_val);
469290282Sobrien		    }
469390282Sobrien#endif /*__alpha__*/
469490282Sobrien
469590282Sobrien		  optimize_size = 0;
469690282Sobrien		}
469790282Sobrien	    }
469890282Sobrien	}
469990282Sobrien    }
470090282Sobrien
470190282Sobrien  if (!optimize)
470290282Sobrien    {
470390282Sobrien      flag_merge_constants = 0;
470490282Sobrien    }
470590282Sobrien
470690282Sobrien  if (optimize >= 1)
470790282Sobrien    {
470890282Sobrien      flag_defer_pop = 1;
470990282Sobrien      flag_thread_jumps = 1;
471090282Sobrien#ifdef DELAY_SLOTS
471190282Sobrien      flag_delayed_branch = 1;
471290282Sobrien#endif
471390282Sobrien#ifdef CAN_DEBUG_WITHOUT_FP
471490282Sobrien      flag_omit_frame_pointer = 1;
471590282Sobrien#endif
471690282Sobrien      flag_guess_branch_prob = 1;
471790282Sobrien      flag_cprop_registers = 1;
471890282Sobrien    }
471990282Sobrien
472090282Sobrien  if (optimize >= 2)
472190282Sobrien    {
472290282Sobrien      flag_optimize_sibling_calls = 1;
472390282Sobrien      flag_cse_follow_jumps = 1;
472490282Sobrien      flag_cse_skip_blocks = 1;
472590282Sobrien      flag_gcse = 1;
472690282Sobrien      flag_expensive_optimizations = 1;
472790282Sobrien      flag_strength_reduce = 1;
472890282Sobrien      flag_rerun_cse_after_loop = 1;
472990282Sobrien      flag_rerun_loop_opt = 1;
473090282Sobrien      flag_caller_saves = 1;
473190282Sobrien      flag_force_mem = 1;
473290282Sobrien      flag_peephole2 = 1;
473390282Sobrien#ifdef INSN_SCHEDULING
473490282Sobrien      flag_schedule_insns = 1;
473590282Sobrien      flag_schedule_insns_after_reload = 1;
473690282Sobrien#endif
473790282Sobrien      flag_regmove = 1;
473890282Sobrien      flag_strict_aliasing = 1;
473990282Sobrien      flag_delete_null_pointer_checks = 1;
474090282Sobrien      flag_reorder_blocks = 1;
474190282Sobrien    }
474290282Sobrien
474390282Sobrien  if (optimize >= 3)
474490282Sobrien    {
474590282Sobrien      flag_inline_functions = 1;
474690282Sobrien      flag_rename_registers = 1;
474790282Sobrien    }
474890282Sobrien
474998573Sobrien  if (optimize_size)
475090282Sobrien    {
475190282Sobrien      align_loops = 1;
475290282Sobrien      align_jumps = 1;
475390282Sobrien      align_labels = 1;
475490282Sobrien      align_functions = 1;
475590282Sobrien    }
475690282Sobrien
475790282Sobrien  /* Initialize whether `char' is signed.  */
475890282Sobrien  flag_signed_char = DEFAULT_SIGNED_CHAR;
475990282Sobrien#ifdef DEFAULT_SHORT_ENUMS
476090282Sobrien  /* Initialize how much space enums occupy, by default.  */
476190282Sobrien  flag_short_enums = DEFAULT_SHORT_ENUMS;
476290282Sobrien#endif
476390282Sobrien
476490282Sobrien  /* Initialize target_flags before OPTIMIZATION_OPTIONS so the latter can
476590282Sobrien     modify it.  */
476690282Sobrien  target_flags = 0;
476790282Sobrien  set_target_switch ("");
476890282Sobrien
476990282Sobrien  /* Unwind tables are always present in an ABI-conformant IA-64
477090282Sobrien     object file, so the default should be ON.  */
477190282Sobrien#ifdef IA64_UNWIND_INFO
477290282Sobrien  flag_unwind_tables = IA64_UNWIND_INFO;
477390282Sobrien#endif
477490282Sobrien
477590282Sobrien#ifdef OPTIMIZATION_OPTIONS
477690282Sobrien  /* Allow default optimizations to be specified on a per-machine basis.  */
477790282Sobrien  OPTIMIZATION_OPTIONS (optimize, optimize_size);
477890282Sobrien#endif
477990282Sobrien
478090282Sobrien  /* Perform normal command line switch decoding.  */
478190282Sobrien  for (i = 1; i < argc;)
478290282Sobrien    {
478390282Sobrien      int lang_processed;
478490282Sobrien      int indep_processed;
478590282Sobrien
478690282Sobrien      /* Give the language a chance to decode the option for itself.  */
478790282Sobrien      lang_processed = (*lang_hooks.decode_option) (argc - i, argv + i);
478890282Sobrien
478990282Sobrien      if (lang_processed >= 0)
479090282Sobrien	/* Now see if the option also has a language independent meaning.
479190282Sobrien	   Some options are both language specific and language independent,
479290282Sobrien	   eg --help.  */
479390282Sobrien	indep_processed = independent_decode_option (argc - i, argv + i);
479490282Sobrien      else
479590282Sobrien	{
479690282Sobrien	  lang_processed = -lang_processed;
479790282Sobrien	  indep_processed = 0;
479890282Sobrien	}
479990282Sobrien
480090282Sobrien      if (lang_processed || indep_processed)
480190282Sobrien	i += MAX (lang_processed, indep_processed);
480290282Sobrien      else
480390282Sobrien	{
480490282Sobrien	  const char *option = NULL;
480590282Sobrien	  const char *lang = NULL;
480690282Sobrien	  unsigned int j;
480790282Sobrien
480890282Sobrien	  /* It is possible that the command line switch is not valid for the
480990282Sobrien	     current language, but it is valid for another language.  In order
481090282Sobrien	     to be compatible with previous versions of the compiler (which
481190282Sobrien	     did not issue an error message in this case) we check for this
481290282Sobrien	     possibility here.  If we do find a match, then if extra_warnings
481390282Sobrien	     is set we generate a warning message, otherwise we will just
481490282Sobrien	     ignore the option.  */
481590282Sobrien	  for (j = 0; j < ARRAY_SIZE (documented_lang_options); j++)
481690282Sobrien	    {
481790282Sobrien	      option = documented_lang_options[j].option;
481890282Sobrien
481990282Sobrien	      if (option == NULL)
482090282Sobrien		lang = documented_lang_options[j].description;
482190282Sobrien	      else if (! strncmp (argv[i], option, strlen (option)))
482290282Sobrien		break;
482390282Sobrien	    }
482490282Sobrien
482590282Sobrien	  if (j != ARRAY_SIZE (documented_lang_options))
482690282Sobrien	    {
482790282Sobrien	      if (extra_warnings)
482890282Sobrien		{
482990282Sobrien		  warning ("ignoring command line option '%s'", argv[i]);
483090282Sobrien		  if (lang)
483190282Sobrien		    warning
483290282Sobrien		      ("(it is valid for %s but not the selected language)",
483390282Sobrien		       lang);
483490282Sobrien		}
483590282Sobrien	    }
483690282Sobrien	  else if (argv[i][0] == '-' && argv[i][1] == 'g')
483790282Sobrien	    warning ("`%s': unknown or unsupported -g option", &argv[i][2]);
483890282Sobrien	  else
483990282Sobrien	    error ("unrecognized option `%s'", argv[i]);
484090282Sobrien
484190282Sobrien	  i++;
484290282Sobrien	}
484390282Sobrien    }
484490282Sobrien
484596289Sobrien  if (flag_no_inline == 2)
484696289Sobrien    flag_no_inline = 0;
484796289Sobrien  else
484896289Sobrien    flag_really_no_inline = flag_no_inline;
484996289Sobrien
485090282Sobrien  /* Set flag_no_inline before the post_options () hook.  The C front
485190282Sobrien     ends use it to determine tree inlining defaults.  FIXME: such
485290282Sobrien     code should be lang-independent when all front ends use tree
485390282Sobrien     inlining, in which case it, and this condition, should be moved
485490282Sobrien     to the top of process_options() instead.  */
485590282Sobrien  if (optimize == 0)
485690282Sobrien    {
485790282Sobrien      /* Inlining does not work if not optimizing,
485890282Sobrien	 so force it not to be done.  */
485990282Sobrien      flag_no_inline = 1;
486090282Sobrien      warn_inline = 0;
486190282Sobrien
486290282Sobrien      /* The c_decode_option function and decode_option hook set
486390282Sobrien	 this to `2' if -Wall is used, so we can avoid giving out
486490282Sobrien	 lots of errors for people who don't realize what -Wall does.  */
486590282Sobrien      if (warn_uninitialized == 1)
486690282Sobrien	warning ("-Wuninitialized is not supported without -O");
486790282Sobrien    }
486890282Sobrien
486996289Sobrien  if (flag_really_no_inline == 2)
487096289Sobrien    flag_really_no_inline = flag_no_inline;
487196289Sobrien
487290282Sobrien  /* All command line options have been parsed; allow the front end to
487390282Sobrien     perform consistency checks, etc.  */
487490282Sobrien  (*lang_hooks.post_options) ();
487590282Sobrien}
487690282Sobrien
487790282Sobrien/* Process the options that have been parsed.  */
487890282Sobrienstatic void
487990282Sobrienprocess_options ()
488050615Sobrien{
488190282Sobrien#ifdef OVERRIDE_OPTIONS
488290282Sobrien  /* Some machines may reject certain combinations of options.  */
488390282Sobrien  OVERRIDE_OPTIONS;
488490282Sobrien#endif
488590282Sobrien
488690282Sobrien  /* Set up the align_*_log variables, defaulting them to 1 if they
488790282Sobrien     were still unset.  */
488890282Sobrien  if (align_loops <= 0) align_loops = 1;
488990282Sobrien  if (align_loops_max_skip > align_loops || !align_loops)
489090282Sobrien    align_loops_max_skip = align_loops - 1;
489190282Sobrien  align_loops_log = floor_log2 (align_loops * 2 - 1);
489290282Sobrien  if (align_jumps <= 0) align_jumps = 1;
489390282Sobrien  if (align_jumps_max_skip > align_jumps || !align_jumps)
489490282Sobrien    align_jumps_max_skip = align_jumps - 1;
489590282Sobrien  align_jumps_log = floor_log2 (align_jumps * 2 - 1);
489690282Sobrien  if (align_labels <= 0) align_labels = 1;
489790282Sobrien  align_labels_log = floor_log2 (align_labels * 2 - 1);
489890282Sobrien  if (align_labels_max_skip > align_labels || !align_labels)
489990282Sobrien    align_labels_max_skip = align_labels - 1;
490090282Sobrien  if (align_functions <= 0) align_functions = 1;
490190282Sobrien  align_functions_log = floor_log2 (align_functions * 2 - 1);
490290282Sobrien
490390282Sobrien  /* Unrolling all loops implies that standard loop unrolling must also
490490282Sobrien     be done.  */
490590282Sobrien  if (flag_unroll_all_loops)
490690282Sobrien    flag_unroll_loops = 1;
490790282Sobrien  /* Loop unrolling requires that strength_reduction be on also.  Silently
490890282Sobrien     turn on strength reduction here if it isn't already on.  Also, the loop
490990282Sobrien     unrolling code assumes that cse will be run after loop, so that must
491090282Sobrien     be turned on also.  */
491190282Sobrien  if (flag_unroll_loops)
491290282Sobrien    {
491390282Sobrien      flag_strength_reduce = 1;
491490282Sobrien      flag_rerun_cse_after_loop = 1;
491590282Sobrien    }
491690282Sobrien
491790282Sobrien  if (flag_non_call_exceptions)
491890282Sobrien    flag_asynchronous_unwind_tables = 1;
491990282Sobrien  if (flag_asynchronous_unwind_tables)
492090282Sobrien    flag_unwind_tables = 1;
492190282Sobrien
492290282Sobrien  /* Warn about options that are not supported on this machine.  */
492390282Sobrien#ifndef INSN_SCHEDULING
492490282Sobrien  if (flag_schedule_insns || flag_schedule_insns_after_reload)
492590282Sobrien    warning ("instruction scheduling not supported on this target machine");
492690282Sobrien#endif
492790282Sobrien#ifndef DELAY_SLOTS
492890282Sobrien  if (flag_delayed_branch)
492990282Sobrien    warning ("this target machine does not have delayed branches");
493090282Sobrien#endif
493190282Sobrien
493290282Sobrien  /* Some operating systems do not allow profiling without a frame
493390282Sobrien     pointer.  */
493490282Sobrien  if (!TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
493590282Sobrien      && profile_flag
493690282Sobrien      && flag_omit_frame_pointer)
493790282Sobrien    {
493890282Sobrien      error ("profiling does not work without a frame pointer");
493990282Sobrien      flag_omit_frame_pointer = 0;
494090282Sobrien    }
494190282Sobrien
494290282Sobrien  user_label_prefix = USER_LABEL_PREFIX;
494390282Sobrien  if (flag_leading_underscore != -1)
494490282Sobrien    {
494590282Sobrien      /* If the default prefix is more complicated than "" or "_",
494690282Sobrien	 issue a warning and ignore this option.  */
494790282Sobrien      if (user_label_prefix[0] == 0 ||
494890282Sobrien	  (user_label_prefix[0] == '_' && user_label_prefix[1] == 0))
494990282Sobrien	{
495090282Sobrien	  user_label_prefix = flag_leading_underscore ? "_" : "";
495190282Sobrien	}
495290282Sobrien      else
495390282Sobrien	warning ("-f%sleading-underscore not supported on this target machine",
495490282Sobrien		 flag_leading_underscore ? "" : "no-");
495590282Sobrien    }
495690282Sobrien
495790282Sobrien  /* If we are in verbose mode, write out the version and maybe all the
495890282Sobrien     option flags in use.  */
495990282Sobrien  if (version_flag)
496090282Sobrien    {
496190282Sobrien      print_version (stderr, "");
496290282Sobrien      if (! quiet_flag)
496390282Sobrien	print_switch_values (stderr, 0, MAX_LINE, "", " ", "\n");
496490282Sobrien    }
496590282Sobrien
496690282Sobrien  if (! quiet_flag)
496790282Sobrien    time_report = 1;
496890282Sobrien
496990282Sobrien  if (flag_syntax_only)
497090282Sobrien    {
497190282Sobrien      write_symbols = NO_DEBUG;
497290282Sobrien      profile_flag = 0;
497390282Sobrien    }
497490282Sobrien
497590282Sobrien  /* Now we know write_symbols, set up the debug hooks based on it.
497690282Sobrien     By default we do nothing for debug output.  */
497790282Sobrien#if defined(DBX_DEBUGGING_INFO)
497850615Sobrien  if (write_symbols == DBX_DEBUG)
497990282Sobrien    debug_hooks = &dbx_debug_hooks;
498050615Sobrien#endif
498190282Sobrien#if defined(XCOFF_DEBUGGING_INFO)
498290282Sobrien  if (write_symbols == XCOFF_DEBUG)
498390282Sobrien    debug_hooks = &xcoff_debug_hooks;
498490282Sobrien#endif
498550615Sobrien#ifdef SDB_DEBUGGING_INFO
498650615Sobrien  if (write_symbols == SDB_DEBUG)
498790282Sobrien    debug_hooks = &sdb_debug_hooks;
498850615Sobrien#endif
498990282Sobrien#ifdef DWARF_DEBUGGING_INFO
499090282Sobrien  if (write_symbols == DWARF_DEBUG)
499190282Sobrien    debug_hooks = &dwarf_debug_hooks;
499290282Sobrien#endif
499390282Sobrien#ifdef DWARF2_DEBUGGING_INFO
499490282Sobrien  if (write_symbols == DWARF2_DEBUG)
499590282Sobrien    debug_hooks = &dwarf2_debug_hooks;
499690282Sobrien#endif
499790282Sobrien#ifdef VMS_DEBUGGING_INFO
499890282Sobrien  if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
499990282Sobrien    debug_hooks = &vmsdbg_debug_hooks;
500090282Sobrien#endif
500190282Sobrien
500290282Sobrien  /* If auxiliary info generation is desired, open the output file.
500390282Sobrien     This goes in the same directory as the source file--unlike
500490282Sobrien     all the other output files.  */
500590282Sobrien  if (flag_gen_aux_info)
500690282Sobrien    {
500790282Sobrien      aux_info_file = fopen (aux_info_file_name, "w");
500890282Sobrien      if (aux_info_file == 0)
500990282Sobrien	fatal_io_error ("can't open %s", aux_info_file_name);
501090282Sobrien    }
501190282Sobrien
501290282Sobrien  if (! targetm.have_named_sections)
501390282Sobrien    {
501490282Sobrien      if (flag_function_sections)
501590282Sobrien	{
501690282Sobrien	  warning ("-ffunction-sections not supported for this target");
501790282Sobrien	  flag_function_sections = 0;
501890282Sobrien	}
501990282Sobrien      if (flag_data_sections)
502090282Sobrien	{
502190282Sobrien	  warning ("-fdata-sections not supported for this target");
502290282Sobrien	  flag_data_sections = 0;
502390282Sobrien	}
502490282Sobrien    }
502590282Sobrien
502690282Sobrien  if (flag_function_sections && profile_flag)
502790282Sobrien    {
502890282Sobrien      warning ("-ffunction-sections disabled; it makes profiling impossible");
502990282Sobrien      flag_function_sections = 0;
503090282Sobrien    }
503190282Sobrien
503290282Sobrien#ifndef HAVE_prefetch
503390282Sobrien  if (flag_prefetch_loop_arrays)
503490282Sobrien    {
503590282Sobrien      warning ("-fprefetch-loop-arrays not supported for this target");
503690282Sobrien      flag_prefetch_loop_arrays = 0;
503790282Sobrien    }
503890282Sobrien#else
503990282Sobrien  if (flag_prefetch_loop_arrays && !HAVE_prefetch)
504090282Sobrien    {
504190282Sobrien      warning ("-fprefetch-loop-arrays not supported for this target (try -march switches)");
504290282Sobrien      flag_prefetch_loop_arrays = 0;
504390282Sobrien    }
504490282Sobrien#endif
504590282Sobrien
504690282Sobrien  /* This combination of options isn't handled for i386 targets and doesn't
504790282Sobrien     make much sense anyway, so don't allow it.  */
504890282Sobrien  if (flag_prefetch_loop_arrays && optimize_size)
504990282Sobrien    {
505090282Sobrien      warning ("-fprefetch-loop-arrays is not supported with -Os");
505190282Sobrien      flag_prefetch_loop_arrays = 0;
505290282Sobrien    }
505390282Sobrien
505490282Sobrien#ifndef OBJECT_FORMAT_ELF
505590282Sobrien  if (flag_function_sections && write_symbols != NO_DEBUG)
505690282Sobrien    warning ("-ffunction-sections may affect debugging on some targets");
505790282Sobrien#endif
505850615Sobrien}
505990282Sobrien
506090282Sobrien/* Language-independent initialization, before language-dependent
506190282Sobrien   initialization.  */
506290282Sobrienstatic void
506390282Sobrienlang_independent_init ()
506490282Sobrien{
506590282Sobrien  decl_printable_name = decl_name;
506690282Sobrien  lang_expand_expr = (lang_expand_expr_t) do_abort;
506750615Sobrien
506890282Sobrien  /* Set the language-dependent identifier size.  */
506990282Sobrien  tree_code_length[(int) IDENTIFIER_NODE]
507090282Sobrien    = ((lang_hooks.identifier_size - sizeof (struct tree_common)
507190282Sobrien	+ sizeof (tree) - 1) / sizeof (tree));
507250615Sobrien
507390282Sobrien  /* Initialize the garbage-collector, and string pools.  */
507490282Sobrien  init_ggc ();
507590282Sobrien  ggc_add_rtx_root (&stack_limit_rtx, 1);
507690282Sobrien  ggc_add_tree_root (&current_function_decl, 1);
507790282Sobrien  ggc_add_tree_root (&current_function_func_begin_label, 1);
507890282Sobrien
507990282Sobrien  init_stringpool ();
508090282Sobrien  init_obstacks ();
508190282Sobrien
508290282Sobrien  init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
508390282Sobrien		  || debug_info_level == DINFO_LEVEL_VERBOSE
508490282Sobrien#ifdef VMS_DEBUGGING_INFO
508590282Sobrien		    /* Enable line number info for traceback */
508690282Sobrien		    || debug_info_level > DINFO_LEVEL_NONE
508790282Sobrien#endif
508890282Sobrien		    || flag_test_coverage
508990282Sobrien		    || warn_notreached);
509090282Sobrien  init_regs ();
509190282Sobrien  init_alias_once ();
509290282Sobrien  init_stmt ();
509390282Sobrien  init_loop ();
509490282Sobrien  init_reload ();
509590282Sobrien  init_function_once ();
509690282Sobrien  init_stor_layout_once ();
509790282Sobrien  init_varasm_once ();
509890282Sobrien  init_EXPR_INSN_LIST_cache ();
509990282Sobrien
510090282Sobrien  /* The following initialization functions need to generate rtl, so
510190282Sobrien     provide a dummy function context for them.  */
510290282Sobrien  init_dummy_function_start ();
510390282Sobrien  init_expmed ();
510490282Sobrien  init_expr_once ();
510590282Sobrien  if (flag_caller_saves)
510690282Sobrien    init_caller_save ();
510790282Sobrien  expand_dummy_function_end ();
510890282Sobrien}
510990282Sobrien
511090282Sobrien/* Language-dependent initialization.  Returns non-zero on success.  */
511190282Sobrienstatic int
511290282Sobrienlang_dependent_init (name)
511390282Sobrien     const char *name;
511450615Sobrien{
511590282Sobrien  if (dump_base_name == 0)
511690282Sobrien    dump_base_name = name ? name : "gccdump";
511790282Sobrien
511890282Sobrien  /* Front-end initialization.  This hook can assume that GC,
511990282Sobrien     identifier hashes etc. are set up, but debug initialization is
512090282Sobrien     not done yet.  This routine must return the original filename
512190282Sobrien     (e.g. foo.i -> foo.c) so can correctly initialize debug output.  */
512290282Sobrien  name = (*lang_hooks.init) (name);
512390282Sobrien  if (name == NULL)
512490282Sobrien    return 0;
512590282Sobrien
512690282Sobrien  /* Is this duplication necessary?  */
512790282Sobrien  name = ggc_strdup (name);
512890282Sobrien  main_input_filename = input_filename = name;
512990282Sobrien  init_asm_output (name);
513090282Sobrien
513190282Sobrien  /* These create various _DECL nodes, so need to be called after the
513290282Sobrien     front end is initialized.  */
513390282Sobrien  init_eh ();
513490282Sobrien  init_optabs ();
513590282Sobrien
513690282Sobrien  /* Put an entry on the input file stack for the main input file.  */
513790282Sobrien  push_srcloc (input_filename, 0);
513890282Sobrien
513990282Sobrien  /* If dbx symbol table desired, initialize writing it and output the
514090282Sobrien     predefined types.  */
514190282Sobrien  timevar_push (TV_SYMOUT);
514290282Sobrien
514390282Sobrien#ifdef DWARF2_UNWIND_INFO
514490282Sobrien  if (dwarf2out_do_frame ())
514590282Sobrien    dwarf2out_frame_init ();
514690282Sobrien#endif
514790282Sobrien
514890282Sobrien  /* Now we have the correct original filename, we can initialize
514990282Sobrien     debug output.  */
515090282Sobrien  (*debug_hooks->init) (name);
515190282Sobrien
515290282Sobrien  timevar_pop (TV_SYMOUT);
515390282Sobrien
515490282Sobrien  return 1;
515550615Sobrien}
515690282Sobrien
515790282Sobrien/* Clean up: close opened files, etc.  */
515850615Sobrien
515990282Sobrienstatic void
516090282Sobrienfinalize ()
516190282Sobrien{
516290282Sobrien  /* Close the dump files.  */
516390282Sobrien  if (flag_gen_aux_info)
516490282Sobrien    {
516590282Sobrien      fclose (aux_info_file);
516690282Sobrien      if (errorcount)
516790282Sobrien	unlink (aux_info_file_name);
516890282Sobrien    }
516950615Sobrien
517090282Sobrien  /* Close non-debugging input and output files.  Take special care to note
517190282Sobrien     whether fclose returns an error, since the pages might still be on the
517290282Sobrien     buffer chain while the file is open.  */
517390282Sobrien
517490282Sobrien  if (asm_out_file)
517590282Sobrien    {
517690282Sobrien      if (ferror (asm_out_file) != 0)
517790282Sobrien	fatal_io_error ("error writing to %s", asm_file_name);
517890282Sobrien      if (fclose (asm_out_file) != 0)
517990282Sobrien	fatal_io_error ("error closing %s", asm_file_name);
518090282Sobrien    }
518190282Sobrien
518290282Sobrien  /* Do whatever is necessary to finish printing the graphs.  */
518390282Sobrien  if (graph_dump_format != no_graph)
518490282Sobrien    {
518590282Sobrien      int i;
518690282Sobrien
518790282Sobrien      for (i = 0; i < (int) DFI_MAX; ++i)
518890282Sobrien	if (dump_file[i].initialized && dump_file[i].graph_dump_p)
518990282Sobrien	  {
519090282Sobrien	    char seq[16];
519190282Sobrien	    char *suffix;
519290282Sobrien
519390282Sobrien	    sprintf (seq, DUMPFILE_FORMAT, i);
519490282Sobrien	    suffix = concat (seq, dump_file[i].extension, NULL);
519590282Sobrien	    finish_graph_dump_file (dump_base_name, suffix);
519690282Sobrien	    free (suffix);
519790282Sobrien	  }
519890282Sobrien    }
519990282Sobrien
520090282Sobrien  if (mem_report)
520190282Sobrien    {
520290282Sobrien      ggc_print_statistics ();
520390282Sobrien      stringpool_statistics ();
520490282Sobrien      dump_tree_statistics ();
520590282Sobrien    }
520690282Sobrien
520790282Sobrien  /* Free up memory for the benefit of leak detectors.  */
520890282Sobrien  free_reg_info ();
520990282Sobrien
521090282Sobrien  /* Language-specific end of compilation actions.  */
521190282Sobrien  (*lang_hooks.finish) ();
521290282Sobrien}
521390282Sobrien
521490282Sobrien/* Initialize the compiler, and compile the input file.  */
521590282Sobrienstatic void
521690282Sobriendo_compile ()
521750615Sobrien{
521890282Sobrien  /* The bulk of command line switch processing.  */
521990282Sobrien  process_options ();
522090282Sobrien
522190282Sobrien  /* We cannot start timing until after options are processed since that
522290282Sobrien     says if we run timers or not.  */
522390282Sobrien  init_timevar ();
522490282Sobrien  timevar_start (TV_TOTAL);
522590282Sobrien
522690282Sobrien  /* Language-independent initialization.  Also sets up GC, identifier
522790282Sobrien     hashes etc.  */
522890282Sobrien  lang_independent_init ();
522990282Sobrien
523090282Sobrien  /* Language-dependent initialization.  Returns true on success.  */
523190282Sobrien  if (lang_dependent_init (filename))
523290282Sobrien    compile_file ();
523390282Sobrien
523490282Sobrien  finalize ();
523590282Sobrien
523690282Sobrien  /* Stop timing and print the times.  */
523790282Sobrien  timevar_stop (TV_TOTAL);
523890282Sobrien  timevar_print (stderr);
523950615Sobrien}
524090282Sobrien
524190282Sobrien/* Entry point of cc1, cc1plus, jc1, f771, etc.
524290282Sobrien   Decode command args, then call compile_file.
524390282Sobrien   Exit code is FATAL_EXIT_CODE if can't open files or if there were
524490282Sobrien   any errors, or SUCCESS_EXIT_CODE if compilation succeeded.
524590282Sobrien
524690282Sobrien   It is not safe to call this function more than once.  */
524790282Sobrien
524890282Sobrienint
524990282Sobrientoplev_main (argc, argv)
525090282Sobrien     int argc;
525190282Sobrien     char **argv;
525290282Sobrien{
525390282Sobrien  hex_init ();
525490282Sobrien
525590282Sobrien  /* Initialization of GCC's environment, and diagnostics.  */
525690282Sobrien  general_init (argv [0]);
525790282Sobrien
525890282Sobrien  /* Parse the options and do minimal processing; basically just
525990282Sobrien     enough to default flags appropriately.  */
526090282Sobrien  parse_options_and_default_flags (argc, argv);
526190282Sobrien
526290282Sobrien  /* Exit early if we can (e.g. -help).  */
526390282Sobrien  if (!exit_after_options)
526490282Sobrien    do_compile ();
526590282Sobrien
526690282Sobrien  if (errorcount || sorrycount)
526790282Sobrien    return (FATAL_EXIT_CODE);
526890282Sobrien
526990282Sobrien  return (SUCCESS_EXIT_CODE);
527090282Sobrien}
5271