toplev.c revision 104765
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 104765 2002-10-10 04:51:11Z kan $ */
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
887104765Skan/* Like align_functions_log above, but used by front-ends to force the
888104765Skan   minimum function alignment.  Zero means no alignment is forced.  */
889104765Skanint force_align_functions_log;
890104765Skan
89150615Sobrien/* Table of supported debugging formats.  */
89290282Sobrienstatic const struct
89350615Sobrien{
89490282Sobrien  const char *const arg;
89550615Sobrien  /* Since PREFERRED_DEBUGGING_TYPE isn't necessarily a
89650615Sobrien     constant expression, we use NO_DEBUG in its place.  */
89790282Sobrien  const enum debug_info_type debug_type;
89890282Sobrien  const int use_extensions_p;
89990282Sobrien  const char *const description;
90050615Sobrien} *da,
90150615Sobriendebug_args[] =
90250615Sobrien{
90390282Sobrien  { "",       NO_DEBUG, DEFAULT_GDB_EXTENSIONS,
90490282Sobrien    N_("Generate debugging info in default format") },
90590282Sobrien  { "gdb",    NO_DEBUG, 1, N_("Generate debugging info in default extended format") },
90650615Sobrien#ifdef DBX_DEBUGGING_INFO
90790282Sobrien  { "stabs",  DBX_DEBUG, 0, N_("Generate STABS format debug info") },
90890282Sobrien  { "stabs+", DBX_DEBUG, 1, N_("Generate extended STABS format debug info") },
90950615Sobrien#endif
91050615Sobrien#ifdef DWARF_DEBUGGING_INFO
91190282Sobrien  { "dwarf",  DWARF_DEBUG, 0, N_("Generate DWARF-1 format debug info") },
91290282Sobrien  { "dwarf+", DWARF_DEBUG, 1,
91390282Sobrien    N_("Generate extended DWARF-1 format debug info") },
91450615Sobrien#endif
91550615Sobrien#ifdef DWARF2_DEBUGGING_INFO
91690282Sobrien  { "dwarf-2", DWARF2_DEBUG, 0, N_("Generate DWARF-2 debug info") },
91750615Sobrien#endif
91850615Sobrien#ifdef XCOFF_DEBUGGING_INFO
91990282Sobrien  { "xcoff",  XCOFF_DEBUG, 0, N_("Generate XCOFF format debug info") },
92090282Sobrien  { "xcoff+", XCOFF_DEBUG, 1, N_("Generate extended XCOFF format debug info") },
92150615Sobrien#endif
92250615Sobrien#ifdef SDB_DEBUGGING_INFO
92390282Sobrien  { "coff", SDB_DEBUG, 0, N_("Generate COFF format debug info") },
92450615Sobrien#endif
92596289Sobrien#ifdef VMS_DEBUGGING_INFO
92696289Sobrien  { "vms", VMS_DEBUG, 0, N_("Generate VMS format debug info") },
92796289Sobrien#endif
92852558Sobrien  { 0, 0, 0, 0 }
92950615Sobrien};
93050615Sobrien
93150615Sobrientypedef struct
93250615Sobrien{
93390282Sobrien  const char *const string;
93490282Sobrien  int *const variable;
93590282Sobrien  const int on_value;
93690282Sobrien  const char *const description;
93750615Sobrien}
93850615Sobrienlang_independent_options;
93950615Sobrien
94090282Sobrienint flag_trapv = 0;
94190282Sobrien
94252558Sobrien/* Add or remove a leading underscore from user symbols.  */
94352558Sobrienint flag_leading_underscore = -1;
94452558Sobrien
94552558Sobrien/* The user symbol prefix after having resolved same.  */
94652558Sobrienconst char *user_label_prefix;
94752558Sobrien
94890282Sobrienstatic const param_info lang_independent_params[] = {
94990282Sobrien#define DEFPARAM(ENUM, OPTION, HELP, DEFAULT) \
95090282Sobrien  { OPTION, DEFAULT, HELP },
95190282Sobrien#include "params.def"
95290282Sobrien#undef DEFPARAM
95390282Sobrien  { NULL, 0, NULL }
95490282Sobrien};
95590282Sobrien
95652558Sobrien/* A default for same.  */
95752558Sobrien#ifndef USER_LABEL_PREFIX
95852558Sobrien#define USER_LABEL_PREFIX ""
95952558Sobrien#endif
96052558Sobrien
96118334Speter/* Table of language-independent -f options.
96218334Speter   STRING is the option name.  VARIABLE is the address of the variable.
96318334Speter   ON_VALUE is the value to store in VARIABLE
96418334Speter    if `-fSTRING' is seen as an option.
96518334Speter   (If `-fno-STRING' is seen as an option, the opposite value is stored.)  */
96618334Speter
96790282Sobrienstatic const lang_independent_options f_options[] =
96818334Speter{
96990282Sobrien  {"format-extensions", &flag_format_extensions, 1,
97090282Sobrien   N_("-Wformat accepts certain FreeBSD system-dependent formats") },
97190282Sobrien  {"eliminate-dwarf2-dups", &flag_eliminate_dwarf2_dups, 1,
97290282Sobrien   N_("Perform DWARF2 duplicate elimination") },
97350615Sobrien  {"float-store", &flag_float_store, 1,
97490282Sobrien   N_("Do not store floats in registers") },
97550615Sobrien  {"volatile", &flag_volatile, 1,
97690282Sobrien   N_("Consider all mem refs through pointers as volatile") },
97750615Sobrien  {"volatile-global", &flag_volatile_global, 1,
97890282Sobrien   N_("Consider all mem refs to global data to be volatile") },
97952558Sobrien  {"volatile-static", &flag_volatile_static, 1,
98090282Sobrien   N_("Consider all mem refs to static data to be volatile") },
98150615Sobrien  {"defer-pop", &flag_defer_pop, 1,
98290282Sobrien   N_("Defer popping functions args from stack until later") },
98350615Sobrien  {"omit-frame-pointer", &flag_omit_frame_pointer, 1,
98490282Sobrien   N_("When possible do not generate stack frames") },
98590282Sobrien  {"optimize-sibling-calls", &flag_optimize_sibling_calls, 1,
98690282Sobrien   N_("Optimize sibling and tail recursive calls") },
98750615Sobrien  {"cse-follow-jumps", &flag_cse_follow_jumps, 1,
98890282Sobrien   N_("When running CSE, follow jumps to their targets") },
98950615Sobrien  {"cse-skip-blocks", &flag_cse_skip_blocks, 1,
99090282Sobrien   N_("When running CSE, follow conditional jumps") },
99150615Sobrien  {"expensive-optimizations", &flag_expensive_optimizations, 1,
99290282Sobrien   N_("Perform a number of minor, expensive optimizations") },
99350615Sobrien  {"thread-jumps", &flag_thread_jumps, 1,
99490282Sobrien   N_("Perform jump threading optimizations") },
99550615Sobrien  {"strength-reduce", &flag_strength_reduce, 1,
99690282Sobrien   N_("Perform strength reduction optimizations") },
99750615Sobrien  {"unroll-loops", &flag_unroll_loops, 1,
99890282Sobrien   N_("Perform loop unrolling when iteration count is known") },
99950615Sobrien  {"unroll-all-loops", &flag_unroll_all_loops, 1,
100090282Sobrien   N_("Perform loop unrolling for all loops") },
100190282Sobrien  {"prefetch-loop-arrays", &flag_prefetch_loop_arrays, 1,
100290282Sobrien   N_("Generate prefetch instructions, if available, for arrays in loops") },
100350615Sobrien  {"move-all-movables", &flag_move_all_movables, 1,
100490282Sobrien   N_("Force all loop invariant computations out of loops") },
100550615Sobrien  {"reduce-all-givs", &flag_reduce_all_givs, 1,
100690282Sobrien   N_("Strength reduce all loop general induction variables") },
100750615Sobrien  {"writable-strings", &flag_writable_strings, 1,
100890282Sobrien   N_("Store strings in writable data section") },
100950615Sobrien  {"peephole", &flag_no_peephole, 0,
101090282Sobrien   N_("Enable machine specific peephole optimizations") },
101150615Sobrien  {"force-mem", &flag_force_mem, 1,
101290282Sobrien   N_("Copy memory operands into registers before using") },
101350615Sobrien  {"force-addr", &flag_force_addr, 1,
101490282Sobrien   N_("Copy memory address constants into regs before using") },
101550615Sobrien  {"function-cse", &flag_no_function_cse, 0,
101690282Sobrien   N_("Allow function addresses to be held in registers") },
101750615Sobrien  {"inline-functions", &flag_inline_functions, 1,
101890282Sobrien   N_("Integrate simple functions into their callers") },
101950615Sobrien  {"keep-inline-functions", &flag_keep_inline_functions, 1,
102090282Sobrien   N_("Generate code for funcs even if they are fully inlined") },
102150615Sobrien  {"inline", &flag_no_inline, 0,
102290282Sobrien   N_("Pay attention to the 'inline' keyword") },
102350615Sobrien  {"keep-static-consts", &flag_keep_static_consts, 1,
102490282Sobrien   N_("Emit static const variables even if they are not used") },
102550615Sobrien  {"syntax-only", &flag_syntax_only, 1,
102690282Sobrien   N_("Check for syntax errors, then stop") },
102750615Sobrien  {"shared-data", &flag_shared_data, 1,
102890282Sobrien   N_("Mark data as shared rather than private") },
102950615Sobrien  {"caller-saves", &flag_caller_saves, 1,
103090282Sobrien   N_("Enable saving registers around function calls") },
103150615Sobrien  {"pcc-struct-return", &flag_pcc_struct_return, 1,
103290282Sobrien   N_("Return 'short' aggregates in memory, not registers") },
103350615Sobrien  {"reg-struct-return", &flag_pcc_struct_return, 0,
103490282Sobrien   N_("Return 'short' aggregates in registers") },
103550615Sobrien  {"delayed-branch", &flag_delayed_branch, 1,
103690282Sobrien   N_("Attempt to fill delay slots of branch instructions") },
103750615Sobrien  {"gcse", &flag_gcse, 1,
103890282Sobrien   N_("Perform the global common subexpression elimination") },
103990282Sobrien  {"gcse-lm", &flag_gcse_lm, 1,
104090282Sobrien   N_("Perform enhanced load motion during global subexpression elimination") },
104190282Sobrien  {"gcse-sm", &flag_gcse_sm, 1,
104290282Sobrien   N_("Perform store motion after global subexpression elimination") },
104350615Sobrien  {"rerun-cse-after-loop", &flag_rerun_cse_after_loop, 1,
104490282Sobrien   N_("Run CSE pass after loop optimizations") },
104550615Sobrien  {"rerun-loop-opt", &flag_rerun_loop_opt, 1,
104690282Sobrien   N_("Run the loop optimizer twice") },
104790282Sobrien  {"delete-null-pointer-checks", &flag_delete_null_pointer_checks, 1,
104890282Sobrien   N_("Delete useless null pointer checks") },
104950615Sobrien  {"pretend-float", &flag_pretend_float, 1,
105090282Sobrien   N_("Pretend that host and target use the same FP format") },
105150615Sobrien  {"schedule-insns", &flag_schedule_insns, 1,
105290282Sobrien   N_("Reschedule instructions before register allocation") },
105350615Sobrien  {"schedule-insns2", &flag_schedule_insns_after_reload, 1,
105490282Sobrien   N_("Reschedule instructions after register allocation") },
105550615Sobrien  {"sched-interblock",&flag_schedule_interblock, 1,
105690282Sobrien   N_("Enable scheduling across basic blocks") },
105750615Sobrien  {"sched-spec",&flag_schedule_speculative, 1,
105890282Sobrien   N_("Allow speculative motion of non-loads") },
105950615Sobrien  {"sched-spec-load",&flag_schedule_speculative_load, 1,
106090282Sobrien   N_("Allow speculative motion of some loads") },
106150615Sobrien  {"sched-spec-load-dangerous",&flag_schedule_speculative_load_dangerous, 1,
106290282Sobrien   N_("Allow speculative motion of more loads") },
106350615Sobrien  {"branch-count-reg",&flag_branch_on_count_reg, 1,
106490282Sobrien   N_("Replace add,compare,branch with branch on count reg") },
106550615Sobrien  {"pic", &flag_pic, 1,
106690282Sobrien   N_("Generate position independent code, if possible") },
106750615Sobrien  {"PIC", &flag_pic, 2, ""},
106850615Sobrien  {"exceptions", &flag_exceptions, 1,
106990282Sobrien   N_("Enable exception handling") },
107090282Sobrien  {"unwind-tables", &flag_unwind_tables, 1,
107190282Sobrien   N_("Just generate unwind tables for exception handling") },
107290282Sobrien  {"asynchronous-unwind-tables", &flag_asynchronous_unwind_tables, 1,
107390282Sobrien   N_("Generate unwind tables exact at each instruction boundary") },
107490282Sobrien  {"non-call-exceptions", &flag_non_call_exceptions, 1,
107590282Sobrien   N_("Support synchronous non-call exceptions") },
107650615Sobrien  {"profile-arcs", &profile_arc_flag, 1,
107790282Sobrien   N_("Insert arc based program profiling code") },
107850615Sobrien  {"test-coverage", &flag_test_coverage, 1,
107990282Sobrien   N_("Create data files needed by gcov") },
108050615Sobrien  {"branch-probabilities", &flag_branch_probabilities, 1,
108190282Sobrien   N_("Use profiling information for branch probabilities") },
108290282Sobrien  {"reorder-blocks", &flag_reorder_blocks, 1,
108390282Sobrien   N_("Reorder basic blocks to improve code placement") },
108490282Sobrien  {"rename-registers", &flag_rename_registers, 1,
108590282Sobrien   N_("Do the register renaming optimization pass") },
108690282Sobrien  {"cprop-registers", &flag_cprop_registers, 1,
108790282Sobrien   N_("Do the register copy-propagation optimization pass") },
108850615Sobrien  {"common", &flag_no_common, 0,
108990282Sobrien   N_("Do not put uninitialized globals in the common section") },
109050615Sobrien  {"inhibit-size-directive", &flag_inhibit_size_directive, 1,
109190282Sobrien   N_("Do not generate .size directives") },
109250615Sobrien  {"function-sections", &flag_function_sections, 1,
109390282Sobrien   N_("place each function into its own section") },
109452558Sobrien  {"data-sections", &flag_data_sections, 1,
109590282Sobrien   N_("place data items into their own section") },
109650615Sobrien  {"verbose-asm", &flag_verbose_asm, 1,
109790282Sobrien   N_("Add extra commentry to assembler output") },
109850615Sobrien  {"gnu-linker", &flag_gnu_linker, 1,
109990282Sobrien   N_("Output GNU ld formatted global initializers") },
110050615Sobrien  {"regmove", &flag_regmove, 1,
110190282Sobrien   N_("Enables a register move optimization") },
110252558Sobrien  {"optimize-register-move", &flag_regmove, 1,
110390282Sobrien   N_("Do the full regmove optimization pass") },
110450615Sobrien  {"pack-struct", &flag_pack_struct, 1,
110590282Sobrien   N_("Pack structure members together without holes") },
110650615Sobrien  {"stack-check", &flag_stack_check, 1,
110790282Sobrien   N_("Insert stack checking code into the program") },
110850615Sobrien  {"argument-alias", &flag_argument_noalias, 0,
110990282Sobrien   N_("Specify that arguments may alias each other & globals") },
111050615Sobrien  {"argument-noalias", &flag_argument_noalias, 1,
111190282Sobrien   N_("Assume arguments may alias globals but not each other") },
111250615Sobrien  {"argument-noalias-global", &flag_argument_noalias, 2,
111390282Sobrien   N_("Assume arguments do not alias each other or globals") },
111450615Sobrien  {"strict-aliasing", &flag_strict_aliasing, 1,
111590282Sobrien   N_("Assume strict aliasing rules apply") },
111690282Sobrien  {"align-loops", &align_loops, 0,
111790282Sobrien   N_("Align the start of loops") },
111890282Sobrien  {"align-jumps", &align_jumps, 0,
111990282Sobrien   N_("Align labels which are only reached by jumping") },
112090282Sobrien  {"align-labels", &align_labels, 0,
112190282Sobrien   N_("Align all labels") },
112290282Sobrien  {"align-functions", &align_functions, 0,
112390282Sobrien   N_("Align the start of functions") },
112490282Sobrien  {"merge-constants", &flag_merge_constants, 1,
112590282Sobrien   N_("Attempt to merge identical constants accross compilation units") },
112690282Sobrien  {"merge-all-constants", &flag_merge_constants, 2,
112790282Sobrien   N_("Attempt to merge identical constants and constant variables") },
112852558Sobrien  {"dump-unnumbered", &flag_dump_unnumbered, 1,
112990282Sobrien   N_("Suppress output of instruction numbers and line number notes in debugging dumps") },
113052558Sobrien  {"instrument-functions", &flag_instrument_function_entry_exit, 1,
113190282Sobrien   N_("Instrument function entry/exit with profiling calls") },
113290282Sobrien  {"ssa", &flag_ssa, 1,
113390282Sobrien   N_("Enable SSA optimizations") },
113490282Sobrien  {"ssa-ccp", &flag_ssa_ccp, 1,
113590282Sobrien   N_("Enable SSA conditional constant propagation") },
113690282Sobrien  {"ssa-dce", &flag_ssa_dce, 1,
113790282Sobrien   N_("Enable aggressive SSA dead code elimination") },
113852558Sobrien  {"leading-underscore", &flag_leading_underscore, 1,
113990282Sobrien   N_("External symbols have a leading underscore") },
114052558Sobrien  {"ident", &flag_no_ident, 0,
114190282Sobrien   N_("Process #ident directives") },
114290282Sobrien  { "peephole2", &flag_peephole2, 1,
114390282Sobrien   N_("Enables an rtl peephole pass run before sched2") },
114490282Sobrien  { "guess-branch-probability", &flag_guess_branch_prob, 1,
114590282Sobrien   N_("Enables guessing of branch probabilities") },
114690282Sobrien  {"math-errno", &flag_errno_math, 1,
114790282Sobrien   N_("Set errno after built-in math functions") },
114890282Sobrien  {"trapping-math", &flag_trapping_math, 1,
114990282Sobrien   N_("Floating-point operations can trap") },
115090282Sobrien  {"unsafe-math-optimizations", &flag_unsafe_math_optimizations, 1,
115190282Sobrien   N_("Allow math optimizations that may violate IEEE or ANSI standards") },
115290282Sobrien  {"bounded-pointers", &flag_bounded_pointers, 1,
115390282Sobrien   N_("Compile pointers as triples: value, base & end") },
115490282Sobrien  {"bounds-check", &flag_bounds_check, 1,
115590282Sobrien   N_("Generate code to check bounds before dereferencing pointers and arrays") },
115690282Sobrien  {"single-precision-constant", &flag_single_precision_constant, 1,
115790282Sobrien   N_("Convert floating point constant to single precision constant") },
115890282Sobrien  {"time-report", &time_report, 1,
115990282Sobrien   N_("Report time taken by each compiler pass at end of run") },
116090282Sobrien  {"mem-report", &mem_report, 1,
116190282Sobrien   N_("Report on permanent memory allocation at end of run") },
116290282Sobrien  { "trapv", &flag_trapv, 1,
116390282Sobrien   N_("Trap for signed overflow in addition / subtraction / multiplication") },
116418334Speter};
116518334Speter
116618334Speter/* Table of language-specific options.  */
116718334Speter
116890282Sobrienstatic const struct lang_opt
116918334Speter{
117090282Sobrien  const char *const option;
117190282Sobrien  const char *const description;
117250615Sobrien}
117350615Sobriendocumented_lang_options[] =
117450615Sobrien{
117550615Sobrien  /* In order not to overload the --help output, the convention
117650615Sobrien     used here is to only describe those options which are not
117750615Sobrien     enabled by default.  */
117818334Speter
117990282Sobrien  { "-ansi",
118090282Sobrien    N_("Compile just for ISO C89") },
118150615Sobrien  { "-fallow-single-precision",
118290282Sobrien    N_("Do not promote floats to double if using -traditional") },
118390282Sobrien  { "-std= ",
118490282Sobrien    N_("Determine language standard") },
118518334Speter
118650615Sobrien  { "-fsigned-bitfields", "" },
118790282Sobrien  { "-funsigned-bitfields",
118890282Sobrien    N_("Make bit-fields by unsigned by default") },
118950615Sobrien  { "-fno-signed-bitfields", "" },
119050615Sobrien  { "-fno-unsigned-bitfields","" },
119190282Sobrien  { "-fsigned-char",
119290282Sobrien    N_("Make 'char' be signed by default") },
119390282Sobrien  { "-funsigned-char",
119490282Sobrien    N_("Make 'char' be unsigned by default") },
119550615Sobrien  { "-fno-signed-char", "" },
119650615Sobrien  { "-fno-unsigned-char", "" },
119718334Speter
119850615Sobrien  { "-ftraditional", "" },
119990282Sobrien  { "-traditional",
120090282Sobrien    N_("Attempt to support traditional K&R style C") },
120150615Sobrien  { "-fnotraditional", "" },
120250615Sobrien  { "-fno-traditional", "" },
120318334Speter
120450615Sobrien  { "-fasm", "" },
120590282Sobrien  { "-fno-asm",
120690282Sobrien    N_("Do not recognize the 'asm' keyword") },
120750615Sobrien  { "-fbuiltin", "" },
120890282Sobrien  { "-fno-builtin",
120990282Sobrien    N_("Do not recognize any built in functions") },
121090282Sobrien  { "-fhosted",
121190282Sobrien    N_("Assume normal C execution environment") },
121250615Sobrien  { "-fno-hosted", "" },
121350615Sobrien  { "-ffreestanding",
121490282Sobrien    N_("Assume that standard libraries & main might not exist") },
121550615Sobrien  { "-fno-freestanding", "" },
121690282Sobrien  { "-fcond-mismatch",
121790282Sobrien    N_("Allow different types as args of ? operator") },
121850615Sobrien  { "-fno-cond-mismatch", "" },
121990282Sobrien  { "-fdollars-in-identifiers",
122090282Sobrien    N_("Allow the use of $ inside identifiers") },
122150615Sobrien  { "-fno-dollars-in-identifiers", "" },
122290282Sobrien  { "-fpreprocessed", "" },
122390282Sobrien  { "-fno-preprocessed", "" },
122490282Sobrien  { "-fshort-double",
122590282Sobrien    N_("Use the same size for double as for float") },
122650615Sobrien  { "-fno-short-double", "" },
122790282Sobrien  { "-fshort-enums",
122890282Sobrien    N_("Use the smallest fitting integer to hold enums") },
122950615Sobrien  { "-fno-short-enums", "" },
123090282Sobrien  { "-fshort-wchar",
123190282Sobrien    N_("Override the underlying type for wchar_t to `unsigned short'") },
123290282Sobrien  { "-fno-short-wchar", "" },
123318334Speter
123490282Sobrien  { "-Wall",
123590282Sobrien    N_("Enable most warning messages") },
123650615Sobrien  { "-Wbad-function-cast",
123790282Sobrien    N_("Warn about casting functions to incompatible types") },
123850615Sobrien  { "-Wno-bad-function-cast", "" },
123952558Sobrien  { "-Wno-missing-noreturn", "" },
124090282Sobrien  { "-Wmissing-format-attribute",
124190282Sobrien    N_("Warn about functions which might be candidates for format attributes") },
124290282Sobrien  { "-Wno-missing-format-attribute", "" },
124390282Sobrien  { "-Wcast-qual",
124490282Sobrien    N_("Warn about casts which discard qualifiers") },
124550615Sobrien  { "-Wno-cast-qual", "" },
124690282Sobrien  { "-Wchar-subscripts",
124790282Sobrien    N_("Warn about subscripts whose type is 'char'") },
124850615Sobrien  { "-Wno-char-subscripts", "" },
124990282Sobrien  { "-Wcomment",
125090282Sobrien    N_("Warn if nested comments are detected") },
125152558Sobrien  { "-Wno-comment", "" },
125290282Sobrien  { "-Wcomments",
125390282Sobrien    N_("Warn if nested comments are detected") },
125452558Sobrien  { "-Wno-comments", "" },
125590282Sobrien  { "-Wconversion",
125690282Sobrien    N_("Warn about possibly confusing type conversions") },
125750615Sobrien  { "-Wno-conversion", "" },
125890282Sobrien  { "-Wformat",
125990282Sobrien    N_("Warn about printf/scanf/strftime/strfmon format anomalies") },
126050615Sobrien  { "-Wno-format", "" },
126190282Sobrien  { "-Wformat-y2k", "" },
126290282Sobrien  { "-Wno-format-y2k",
126390282Sobrien    N_("Don't warn about strftime formats yielding 2 digit years") },
126490282Sobrien  { "-Wformat-extra-args", "" },
126590282Sobrien  { "-Wno-format-extra-args",
126690282Sobrien    N_("Don't warn about too many arguments to format functions") },
126790282Sobrien  { "-Wformat-nonliteral",
126890282Sobrien    N_("Warn about non-string-literal format strings") },
126990282Sobrien  { "-Wno-format-nonliteral", "" },
127090282Sobrien  { "-Wformat-security",
127190282Sobrien    N_("Warn about possible security problems with format functions") },
127290282Sobrien  { "-Wno-format-security", "" },
127350615Sobrien  { "-Wimplicit-function-declaration",
127490282Sobrien    N_("Warn about implicit function declarations") },
127550615Sobrien  { "-Wno-implicit-function-declaration", "" },
127650615Sobrien  { "-Werror-implicit-function-declaration", "" },
127790282Sobrien  { "-Wimplicit-int",
127890282Sobrien    N_("Warn when a declaration does not specify a type") },
127950615Sobrien  { "-Wno-implicit-int", "" },
128050615Sobrien  { "-Wimplicit", "" },
128150615Sobrien  { "-Wno-implicit", "" },
128290282Sobrien  { "-Wimport",
128390282Sobrien    N_("Warn about the use of the #import directive") },
128450615Sobrien  { "-Wno-import", "" },
128550615Sobrien  { "-Wlong-long","" },
128690282Sobrien  { "-Wno-long-long",
128790282Sobrien    N_("Do not warn about using 'long long' when -pedantic") },
128890282Sobrien  { "-Wmain",
128990282Sobrien    N_("Warn about suspicious declarations of main") },
129050615Sobrien  { "-Wno-main", "" },
129150615Sobrien  { "-Wmissing-braces",
129290282Sobrien    N_("Warn about possibly missing braces around initializers") },
129350615Sobrien  { "-Wno-missing-braces", "" },
129450615Sobrien  { "-Wmissing-declarations",
129590282Sobrien    N_("Warn about global funcs without previous declarations") },
129650615Sobrien  { "-Wno-missing-declarations", "" },
129790282Sobrien  { "-Wmissing-prototypes",
129890282Sobrien    N_("Warn about global funcs without prototypes") },
129950615Sobrien  { "-Wno-missing-prototypes", "" },
130090282Sobrien  { "-Wmultichar",
130190282Sobrien    N_("Warn about use of multicharacter literals") },
130250615Sobrien  { "-Wno-multichar", "" },
130390282Sobrien  { "-Wnested-externs",
130490282Sobrien    N_("Warn about externs not at file scope level") },
130550615Sobrien  { "-Wno-nested-externs", "" },
130690282Sobrien  { "-Wparentheses",
130790282Sobrien    N_("Warn about possible missing parentheses") },
130850615Sobrien  { "-Wno-parentheses", "" },
130990282Sobrien  { "-Wsequence-point",
131090282Sobrien    N_("Warn about possible violations of sequence point rules") },
131190282Sobrien  { "-Wno-sequence-point", "" },
131290282Sobrien  { "-Wpointer-arith",
131390282Sobrien    N_("Warn about function pointer arithmetic") },
131450615Sobrien  { "-Wno-pointer-arith", "" },
131550615Sobrien  { "-Wredundant-decls",
131690282Sobrien    N_("Warn about multiple declarations of the same object") },
131750615Sobrien  { "-Wno-redundant-decls", "" },
131890282Sobrien  { "-Wsign-compare",
131990282Sobrien    N_("Warn about signed/unsigned comparisons") },
132050615Sobrien  { "-Wno-sign-compare", "" },
132190282Sobrien  { "-Wfloat-equal",
132290282Sobrien    N_("Warn about testing equality of floating point numbers") },
132390282Sobrien  { "-Wno-float-equal", "" },
132490282Sobrien  { "-Wunknown-pragmas",
132590282Sobrien    N_("Warn about unrecognized pragmas") },
132650615Sobrien  { "-Wno-unknown-pragmas", "" },
132790282Sobrien  { "-Wstrict-prototypes",
132890282Sobrien    N_("Warn about non-prototyped function decls") },
132950615Sobrien  { "-Wno-strict-prototypes", "" },
133090282Sobrien  { "-Wtraditional",
133190282Sobrien    N_("Warn about constructs whose meaning change in ISO C") },
133250615Sobrien  { "-Wno-traditional", "" },
133390282Sobrien  { "-Wtrigraphs",
133490282Sobrien    N_("Warn when trigraphs are encountered") },
133550615Sobrien  { "-Wno-trigraphs", "" },
133650615Sobrien  { "-Wundef", "" },
133750615Sobrien  { "-Wno-undef", "" },
133890282Sobrien  { "-Wwrite-strings",
133990282Sobrien    N_("Mark strings as 'const char *'") },
134050615Sobrien  { "-Wno-write-strings", "" },
134118334Speter
134250615Sobrien#define DEFINE_LANG_NAME(NAME) { NULL, NAME },
134350615Sobrien
134418334Speter#include "options.h"
134590282Sobrien
134618334Speter};
134750615Sobrien
134850615Sobrien/* Here is a table, controlled by the tm.h file, listing each -m switch
134950615Sobrien   and which bits in `target_switches' it should set or clear.
135050615Sobrien   If VALUE is positive, it is bits to set.
135150615Sobrien   If VALUE is negative, -VALUE is bits to clear.
135250615Sobrien   (The sign bit is not used so there is no confusion.)  */
135350615Sobrien
135490282Sobrienstatic const struct
135550615Sobrien{
135690282Sobrien  const char *const name;
135790282Sobrien  const int value;
135890282Sobrien  const char *const description;
135950615Sobrien}
136050615Sobrientarget_switches [] = TARGET_SWITCHES;
136150615Sobrien
136250615Sobrien/* This table is similar, but allows the switch to have a value.  */
136350615Sobrien
136450615Sobrien#ifdef TARGET_OPTIONS
136590282Sobrienstatic const struct
136650615Sobrien{
136790282Sobrien  const char *const prefix;
136890282Sobrien  const char **const variable;
136990282Sobrien  const char *const description;
137050615Sobrien}
137150615Sobrientarget_options [] = TARGET_OPTIONS;
137250615Sobrien#endif
137318334Speter
137490282Sobrien/* Options controlling warnings.  */
137518334Speter
137618334Speter/* Don't print warning messages.  -w.  */
137718334Speter
137818334Speterint inhibit_warnings = 0;
137918334Speter
138090282Sobrien/* Don't suppress warnings from system headers.  -Wsystem-headers.  */
138190282Sobrien
138290282Sobrienint warn_system_headers = 0;
138390282Sobrien
138418334Speter/* Print various extra warnings.  -W.  */
138518334Speter
138618334Speterint extra_warnings = 0;
138718334Speter
138818334Speter/* Treat warnings as errors.  -Werror.  */
138918334Speter
139018334Speterint warnings_are_errors = 0;
139118334Speter
139290282Sobrien/* Nonzero to warn about unused variables, functions et.al.  */
139318334Speter
139490282Sobrienint warn_unused_function;
139590282Sobrienint warn_unused_label;
139690282Sobrienint warn_unused_parameter;
139790282Sobrienint warn_unused_variable;
139890282Sobrienint warn_unused_value;
139918334Speter
140090282Sobrien/* Nonzero to warn about code which is never reached.  */
140190282Sobrien
140290282Sobrienint warn_notreached;
140390282Sobrien
140418334Speter/* Nonzero to warn about variables used before they are initialized.  */
140518334Speter
140618334Speterint warn_uninitialized;
140718334Speter
140890282Sobrien/* Nonzero means warn about all declarations which shadow others.  */
140918334Speter
141018334Speterint warn_shadow;
141118334Speter
141218334Speter/* Warn if a switch on an enum fails to have a case for every enum value.  */
141318334Speter
141418334Speterint warn_switch;
141518334Speter
141618334Speter/* Nonzero means warn about function definitions that default the return type
141718334Speter   or that use a null return and have a return-type other than void.  */
141818334Speter
141918334Speterint warn_return_type;
142018334Speter
142118334Speter/* Nonzero means warn about pointer casts that increase the required
142218334Speter   alignment of the target type (and might therefore lead to a crash
142318334Speter   due to a misaligned access).  */
142418334Speter
142518334Speterint warn_cast_align;
142618334Speter
142718334Speter/* Nonzero means warn about any objects definitions whose size is larger
142818334Speter   than N bytes.  Also want about function definitions whose returned
142918334Speter   values are larger than N bytes. The value N is in `larger_than_size'.  */
143090282Sobrien
143118334Speterint warn_larger_than;
143290282SobrienHOST_WIDE_INT larger_than_size;
143318334Speter
143418334Speter/* Nonzero means warn if inline function is too large.  */
143518334Speter
143618334Speterint warn_inline;
143718334Speter
143818334Speter/* Warn if a function returns an aggregate,
143918334Speter   since there are often incompatible calling conventions for doing this.  */
144018334Speter
144118334Speterint warn_aggregate_return;
144218334Speter
144390282Sobrien/* Warn if packed attribute on struct is unnecessary and inefficient.  */
144490282Sobrien
144590282Sobrienint warn_packed;
144690282Sobrien
144790282Sobrien/* Warn when gcc pads a structure to an alignment boundary.  */
144890282Sobrien
144990282Sobrienint warn_padded;
145090282Sobrien
145190282Sobrien/* Warn when an optimization pass is disabled.  */
145290282Sobrien
145390282Sobrienint warn_disabled_optimization;
145490282Sobrien
145590282Sobrien/* Warn about functions which might be candidates for attribute noreturn.  */
145690282Sobrien
145790282Sobrienint warn_missing_noreturn;
145890282Sobrien
145990282Sobrien/* Nonzero means warn about uses of __attribute__((deprecated))
146090282Sobrien   declarations.  */
146190282Sobrien
146290282Sobrienint warn_deprecated_decl = 1;
146390282Sobrien
146418334Speter/* Likewise for -W.  */
146518334Speter
146690282Sobrienstatic const lang_independent_options W_options[] =
146718334Speter{
146890282Sobrien  {"unused-function", &warn_unused_function, 1,
146990282Sobrien   N_("Warn when a function is unused") },
147090282Sobrien  {"unused-label", &warn_unused_label, 1,
147190282Sobrien   N_("Warn when a label is unused") },
147290282Sobrien  {"unused-parameter", &warn_unused_parameter, 1,
147390282Sobrien   N_("Warn when a function parameter is unused") },
147490282Sobrien  {"unused-variable", &warn_unused_variable, 1,
147590282Sobrien   N_("Warn when a variable is unused") },
147690282Sobrien  {"unused-value", &warn_unused_value, 1,
147790282Sobrien   N_("Warn when an expression value is unused") },
147890282Sobrien  {"system-headers", &warn_system_headers, 1,
147990282Sobrien   N_("Do not suppress warnings from system headers") },
148090282Sobrien  {"error", &warnings_are_errors, 1,
148190282Sobrien   N_("Treat all warnings as errors") },
148290282Sobrien  {"shadow", &warn_shadow, 1,
148390282Sobrien   N_("Warn when one local variable shadows another") },
148450615Sobrien  {"switch", &warn_switch, 1,
148590282Sobrien   N_("Warn about enumerated switches missing a specific case") },
148650615Sobrien  {"aggregate-return", &warn_aggregate_return, 1,
148790282Sobrien   N_("Warn about returning structures, unions or arrays") },
148850615Sobrien  {"cast-align", &warn_cast_align, 1,
148990282Sobrien   N_("Warn about pointer casts which increase alignment") },
149090282Sobrien  {"unreachable-code", &warn_notreached, 1,
149190282Sobrien   N_("Warn about code that will never be executed") },
149250615Sobrien  {"uninitialized", &warn_uninitialized, 1,
149390282Sobrien   N_("Warn about uninitialized automatic variables") },
149450615Sobrien  {"inline", &warn_inline, 1,
149590282Sobrien   N_("Warn when an inlined function cannot be inlined") },
149690282Sobrien  {"packed", &warn_packed, 1,
149790282Sobrien   N_("Warn when the packed attribute has no effect on struct layout") },
149890282Sobrien  {"padded", &warn_padded, 1,
149990282Sobrien   N_("Warn when padding is required to align struct members") },
150090282Sobrien  {"disabled-optimization", &warn_disabled_optimization, 1,
150190282Sobrien   N_("Warn when an optimization pass is disabled") },
150290282Sobrien  {"deprecated-declarations", &warn_deprecated_decl, 1,
150390282Sobrien   N_("Warn about uses of __attribute__((deprecated)) declarations") },
150490282Sobrien  {"missing-noreturn", &warn_missing_noreturn, 1,
150590282Sobrien   N_("Warn about functions which might be candidates for attribute noreturn") }
150618334Speter};
150790282Sobrien
150890282Sobrienvoid
150990282Sobrienset_Wunused (setting)
151090282Sobrien     int setting;
151190282Sobrien{
151290282Sobrien  warn_unused_function = setting;
151390282Sobrien  warn_unused_label = setting;
151490282Sobrien  /* Unused function parameter warnings are reported when either ``-W
151590282Sobrien     -Wunused'' or ``-Wunused-parameter'' is specified.  Differentiate
151690282Sobrien     -Wunused by setting WARN_UNUSED_PARAMETER to -1.  */
151790282Sobrien  if (!setting)
151890282Sobrien    warn_unused_parameter = 0;
151990282Sobrien  else if (!warn_unused_parameter)
152090282Sobrien    warn_unused_parameter = -1;
152190282Sobrien  warn_unused_variable = setting;
152290282Sobrien  warn_unused_value = setting;
152390282Sobrien}
152490282Sobrien
152590282Sobrien/* The following routines are useful in setting all the flags that
152690282Sobrien   -ffast-math and -fno-fast-math imply.  */
152790282Sobrien
152890282Sobrienvoid
152990282Sobrienset_fast_math_flags ()
153090282Sobrien{
153190282Sobrien  flag_trapping_math = 0;
153290282Sobrien  flag_unsafe_math_optimizations = 1;
153390282Sobrien  flag_errno_math = 0;
153490282Sobrien}
153590282Sobrien
153690282Sobrienvoid
153790282Sobrienset_no_fast_math_flags ()
153890282Sobrien{
153990282Sobrien  flag_trapping_math = 1;
154090282Sobrien  flag_unsafe_math_optimizations = 0;
154190282Sobrien  flag_errno_math = 1;
154290282Sobrien}
154390282Sobrien
154418334Speter
154518334Speter/* Output files for assembler code (real compiler output)
154618334Speter   and debugging dumps.  */
154718334Speter
154818334SpeterFILE *asm_out_file;
154918334SpeterFILE *aux_info_file;
155050615SobrienFILE *rtl_dump_file = NULL;
155118334Speter
155252558Sobrien/* Decode the string P as an integral parameter.
155352558Sobrien   If the string is indeed an integer return its numeric value else
155452558Sobrien   issue an Invalid Option error for the option PNAME and return DEFVAL.
155590282Sobrien   If PNAME is zero just return DEFVAL, do not call error.  */
155690282Sobrien
155752558Sobrienint
155852558Sobrienread_integral_parameter (p, pname, defval)
155952558Sobrien     const char *p;
156052558Sobrien     const char *pname;
156152558Sobrien     const int  defval;
156252558Sobrien{
156352558Sobrien  const char *endp = p;
156452558Sobrien
156552558Sobrien  while (*endp)
156652558Sobrien    {
156790282Sobrien      if (ISDIGIT (*endp))
156852558Sobrien	endp++;
156952558Sobrien      else
157052558Sobrien	break;
157152558Sobrien    }
157252558Sobrien
157352558Sobrien  if (*endp != 0)
157452558Sobrien    {
157552558Sobrien      if (pname != 0)
157690282Sobrien	error ("invalid option `%s'", pname);
157752558Sobrien      return defval;
157852558Sobrien    }
157952558Sobrien
158052558Sobrien  return atoi (p);
158152558Sobrien}
158252558Sobrien
158318334Speter
158418334Speter/* This is the default decl_printable_name function.  */
158518334Speter
158690282Sobrienstatic const char *
158750615Sobriendecl_name (decl, verbosity)
158818334Speter     tree decl;
158952558Sobrien     int verbosity ATTRIBUTE_UNUSED;
159018334Speter{
159118334Speter  return IDENTIFIER_POINTER (DECL_NAME (decl));
159218334Speter}
159318334Speter
159418334Speter
159518334Speter/* This calls abort and is used to avoid problems when abort if a macro.
159618334Speter   It is used when we need to pass the address of abort.  */
159718334Speter
159818334Spetervoid
159918334Speterdo_abort ()
160018334Speter{
160118334Speter  abort ();
160218334Speter}
160318334Speter
160418334Speter/* When `malloc.c' is compiled with `rcheck' defined,
160518334Speter   it calls this function to report clobberage.  */
160618334Speter
160718334Spetervoid
160818334Speterbotch (s)
160990282Sobrien     const char *s ATTRIBUTE_UNUSED;
161018334Speter{
161118334Speter  abort ();
161218334Speter}
161318334Speter
161418334Speter/* Return the logarithm of X, base 2, considering X unsigned,
161518334Speter   if X is a power of 2.  Otherwise, returns -1.
161618334Speter
161718334Speter   This should be used via the `exact_log2' macro.  */
161818334Speter
161918334Speterint
162018334Speterexact_log2_wide (x)
162190282Sobrien     unsigned HOST_WIDE_INT x;
162218334Speter{
162390282Sobrien  int log = 0;
162418334Speter  /* Test for 0 or a power of 2.  */
162518334Speter  if (x == 0 || x != (x & -x))
162618334Speter    return -1;
162718334Speter  while ((x >>= 1) != 0)
162818334Speter    log++;
162918334Speter  return log;
163018334Speter}
163118334Speter
163218334Speter/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
163318334Speter   If X is 0, return -1.
163418334Speter
163518334Speter   This should be used via the floor_log2 macro.  */
163618334Speter
163718334Speterint
163818334Speterfloor_log2_wide (x)
163990282Sobrien     unsigned HOST_WIDE_INT x;
164018334Speter{
164190282Sobrien  int log = -1;
164218334Speter  while (x != 0)
164318334Speter    log++,
164418334Speter    x >>= 1;
164518334Speter  return log;
164618334Speter}
164718334Speter
164850615Sobrienstatic int float_handler_set;
164918334Speterint float_handled;
165018334Speterjmp_buf float_handler;
165118334Speter
165250615Sobrien/* Signals actually come here.  */
165350615Sobrien
165450615Sobrienstatic void
165550615Sobrienfloat_signal (signo)
165650615Sobrien     /* If this is missing, some compilers complain.  */
165750615Sobrien     int signo ATTRIBUTE_UNUSED;
165850615Sobrien{
165950615Sobrien  if (float_handled == 0)
166090282Sobrien    crash_signal (signo);
166150615Sobrien  float_handled = 0;
166290282Sobrien
166390282Sobrien  /* On System-V derived systems, we must reinstall the signal handler.
166490282Sobrien     This is harmless on BSD-derived systems.  */
166550615Sobrien  signal (SIGFPE, float_signal);
166650615Sobrien  longjmp (float_handler, 1);
166750615Sobrien}
166850615Sobrien
166918334Speter/* Specify where to longjmp to when a floating arithmetic error happens.
167018334Speter   If HANDLER is 0, it means don't handle the errors any more.  */
167118334Speter
167290282Sobrienstatic void
167318334Speterset_float_handler (handler)
167418334Speter     jmp_buf handler;
167518334Speter{
167618334Speter  float_handled = (handler != 0);
167718334Speter  if (handler)
167890282Sobrien    memcpy (float_handler, handler, sizeof (float_handler));
167950615Sobrien
168050615Sobrien  if (float_handled && ! float_handler_set)
168150615Sobrien    {
168250615Sobrien      signal (SIGFPE, float_signal);
168350615Sobrien      float_handler_set = 1;
168450615Sobrien    }
168518334Speter}
168618334Speter
168752558Sobrien/* This is a wrapper function for code which might elicit an
168852558Sobrien   arithmetic exception.  That code should be passed in as a function
168952558Sobrien   pointer FN, and one argument DATA.  DATA is usually a struct which
169052558Sobrien   contains the real input and output for function FN.  This function
169152558Sobrien   returns 0 (failure) if longjmp was called (i.e. an exception
169290282Sobrien   occurred.)  It returns 1 (success) otherwise.  */
169352558Sobrien
169452558Sobrienint
169552558Sobriendo_float_handler (fn, data)
169690282Sobrien     void (*fn) PARAMS ((PTR));
169790282Sobrien     PTR data;
169852558Sobrien{
169952558Sobrien  jmp_buf buf;
170052558Sobrien
170152558Sobrien  if (setjmp (buf))
170252558Sobrien    {
170390282Sobrien      /* We got here via longjmp () caused by an exception in function
170490282Sobrien         fn ().  */
170552558Sobrien      set_float_handler (NULL);
170652558Sobrien      return 0;
170752558Sobrien    }
170852558Sobrien
170952558Sobrien  set_float_handler (buf);
171052558Sobrien  (*fn)(data);
171152558Sobrien  set_float_handler (NULL);
171252558Sobrien  return 1;
171352558Sobrien}
171452558Sobrien
171590282Sobrien/* Handler for fatal signals, such as SIGSEGV.  These are transformed
171690282Sobrien   into ICE messages, which is much more user friendly.  */
171718334Speter
171818334Speterstatic void
171990282Sobriencrash_signal (signo)
172090282Sobrien     int signo;
172118334Speter{
172290282Sobrien  internal_error ("internal error: %s", strsignal (signo));
172318334Speter}
172418334Speter
172518334Speter/* Strip off a legitimate source ending from the input string NAME of
172618334Speter   length LEN.  Rather than having to know the names used by all of
172750615Sobrien   our front ends, we strip off an ending of a period followed by
172890282Sobrien   up to five characters.  (Java uses ".class".)  */
172918334Speter
173018334Spetervoid
173118334Speterstrip_off_ending (name, len)
173218334Speter     char *name;
173318334Speter     int len;
173418334Speter{
173550615Sobrien  int i;
173650615Sobrien  for (i = 2;  i < 6 && len > i;  i++)
173750615Sobrien    {
173850615Sobrien      if (name[len - i] == '.')
173950615Sobrien	{
174050615Sobrien	  name[len - i] = '\0';
174150615Sobrien	  break;
174250615Sobrien	}
174350615Sobrien    }
174418334Speter}
174518334Speter
174618334Speter/* Output a quoted string.  */
174750615Sobrien
174818334Spetervoid
174918334Speteroutput_quoted_string (asm_file, string)
175018334Speter     FILE *asm_file;
175152558Sobrien     const char *string;
175218334Speter{
175350615Sobrien#ifdef OUTPUT_QUOTED_STRING
175450615Sobrien  OUTPUT_QUOTED_STRING (asm_file, string);
175550615Sobrien#else
175618334Speter  char c;
175718334Speter
175818334Speter  putc ('\"', asm_file);
175918334Speter  while ((c = *string++) != 0)
176018334Speter    {
176196289Sobrien      if (ISPRINT (c))
176296289Sobrien	{
176396289Sobrien	  if (c == '\"' || c == '\\')
176496289Sobrien	    putc ('\\', asm_file);
176596289Sobrien	  putc (c, asm_file);
176696289Sobrien	}
176796289Sobrien      else
176896289Sobrien	fprintf (asm_file, "\\%03o", c);
176918334Speter    }
177018334Speter  putc ('\"', asm_file);
177150615Sobrien#endif
177218334Speter}
177318334Speter
177418334Speter/* Output a file name in the form wanted by System V.  */
177518334Speter
177618334Spetervoid
177718334Speteroutput_file_directive (asm_file, input_name)
177818334Speter     FILE *asm_file;
177952558Sobrien     const char *input_name;
178018334Speter{
178118334Speter  int len = strlen (input_name);
178252558Sobrien  const char *na = input_name + len;
178318334Speter
178418334Speter  /* NA gets INPUT_NAME sans directory names.  */
178518334Speter  while (na > input_name)
178618334Speter    {
178790282Sobrien      if (IS_DIR_SEPARATOR (na[-1]))
178890282Sobrien        break;
178918334Speter      na--;
179018334Speter    }
179118334Speter
179218334Speter#ifdef ASM_OUTPUT_MAIN_SOURCE_FILENAME
179318334Speter  ASM_OUTPUT_MAIN_SOURCE_FILENAME (asm_file, na);
179418334Speter#else
179518334Speter#ifdef ASM_OUTPUT_SOURCE_FILENAME
179618334Speter  ASM_OUTPUT_SOURCE_FILENAME (asm_file, na);
179718334Speter#else
179818334Speter  fprintf (asm_file, "\t.file\t");
179918334Speter  output_quoted_string (asm_file, na);
180018334Speter  fputc ('\n', asm_file);
180118334Speter#endif
180218334Speter#endif
180318334Speter}
180418334Speter
180590282Sobrien/* Routine to open a dump file.  Return true if the dump file is enabled.  */
180618334Speter
180790282Sobrienstatic int
180890282Sobrienopen_dump_file (index, decl)
180990282Sobrien     enum dump_file_index index;
181090282Sobrien     tree decl;
181118334Speter{
181290282Sobrien  char *dump_name;
181390282Sobrien  const char *open_arg;
181490282Sobrien  char seq[16];
181518334Speter
181690282Sobrien  if (! dump_file[index].enabled)
181790282Sobrien    return 0;
181850615Sobrien
181990282Sobrien  timevar_push (TV_DUMP);
182090282Sobrien  if (rtl_dump_file != NULL)
182190282Sobrien    fclose (rtl_dump_file);
182250615Sobrien
182390282Sobrien  sprintf (seq, DUMPFILE_FORMAT, index);
182450615Sobrien
182590282Sobrien  if (! dump_file[index].initialized)
182690282Sobrien    {
182790282Sobrien      /* If we've not initialized the files, do so now.  */
182890282Sobrien      if (graph_dump_format != no_graph
182990282Sobrien	  && dump_file[index].graph_dump_p)
183090282Sobrien	{
183190282Sobrien	  dump_name = concat (seq, dump_file[index].extension, NULL);
183290282Sobrien	  clean_graph_dump_file (dump_base_name, dump_name);
183390282Sobrien	  free (dump_name);
183490282Sobrien	}
183590282Sobrien      dump_file[index].initialized = 1;
183690282Sobrien      open_arg = "w";
183790282Sobrien    }
183890282Sobrien  else
183990282Sobrien    open_arg = "a";
184050615Sobrien
184190282Sobrien  dump_name = concat (dump_base_name, seq,
184290282Sobrien		      dump_file[index].extension, NULL);
184350615Sobrien
184490282Sobrien  rtl_dump_file = fopen (dump_name, open_arg);
184590282Sobrien  if (rtl_dump_file == NULL)
184690282Sobrien    fatal_io_error ("can't open %s", dump_name);
184790282Sobrien
184890282Sobrien  free (dump_name);
184990282Sobrien
185090282Sobrien  if (decl)
185190282Sobrien    fprintf (rtl_dump_file, "\n;; Function %s\n\n",
185290282Sobrien	     decl_printable_name (decl, 2));
185390282Sobrien
185490282Sobrien  timevar_pop (TV_DUMP);
185590282Sobrien  return 1;
185650615Sobrien}
185750615Sobrien
185890282Sobrien/* Routine to close a dump file.  */
185990282Sobrien
186050615Sobrienstatic void
186190282Sobrienclose_dump_file (index, func, insns)
186290282Sobrien     enum dump_file_index index;
186390282Sobrien     void (*func) PARAMS ((FILE *, rtx));
186490282Sobrien     rtx insns;
186550615Sobrien{
186690282Sobrien  if (! rtl_dump_file)
186790282Sobrien    return;
186850615Sobrien
186990282Sobrien  timevar_push (TV_DUMP);
187090282Sobrien  if (insns
187190282Sobrien      && graph_dump_format != no_graph
187290282Sobrien      && dump_file[index].graph_dump_p)
187390282Sobrien    {
187490282Sobrien      char seq[16];
187590282Sobrien      char *suffix;
187650615Sobrien
187790282Sobrien      sprintf (seq, DUMPFILE_FORMAT, index);
187890282Sobrien      suffix = concat (seq, dump_file[index].extension, NULL);
187990282Sobrien      print_rtl_graph_with_bb (dump_base_name, suffix, insns);
188090282Sobrien      free (suffix);
188190282Sobrien    }
188250615Sobrien
188390282Sobrien  if (func && insns)
188490282Sobrien    func (rtl_dump_file, insns);
188550615Sobrien
188690282Sobrien  fflush (rtl_dump_file);
188790282Sobrien  fclose (rtl_dump_file);
188850615Sobrien
188950615Sobrien  rtl_dump_file = NULL;
189090282Sobrien  timevar_pop (TV_DUMP);
189118334Speter}
189218334Speter
189352558Sobrien/* Do any final processing required for the declarations in VEC, of
189452558Sobrien   which there are LEN.  We write out inline functions and variables
189552558Sobrien   that have been deferred until this point, but which are required.
189690282Sobrien   Returns non-zero if anything was put out.  */
189790282Sobrien
189852558Sobrienint
189952558Sobrienwrapup_global_declarations (vec, len)
190052558Sobrien     tree *vec;
190152558Sobrien     int len;
190252558Sobrien{
190352558Sobrien  tree decl;
190452558Sobrien  int i;
190552558Sobrien  int reconsider;
190652558Sobrien  int output_something = 0;
190750615Sobrien
190852558Sobrien  for (i = 0; i < len; i++)
190952558Sobrien    {
191052558Sobrien      decl = vec[i];
191190282Sobrien
191252558Sobrien      /* We're not deferring this any longer.  */
191352558Sobrien      DECL_DEFER_OUTPUT (decl) = 0;
191490282Sobrien
191552558Sobrien      if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0
191652558Sobrien	  && incomplete_decl_finalize_hook != 0)
191752558Sobrien	(*incomplete_decl_finalize_hook) (decl);
191852558Sobrien    }
191952558Sobrien
192052558Sobrien  /* Now emit any global variables or functions that we have been
192152558Sobrien     putting off.  We need to loop in case one of the things emitted
192252558Sobrien     here references another one which comes earlier in the list.  */
192352558Sobrien  do
192452558Sobrien    {
192552558Sobrien      reconsider = 0;
192652558Sobrien      for (i = 0; i < len; i++)
192752558Sobrien	{
192852558Sobrien	  decl = vec[i];
192952558Sobrien
193052558Sobrien	  if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl))
193152558Sobrien	    continue;
193252558Sobrien
193352558Sobrien	  /* Don't write out static consts, unless we still need them.
193452558Sobrien
193552558Sobrien	     We also keep static consts if not optimizing (for debugging),
193652558Sobrien	     unless the user specified -fno-keep-static-consts.
193752558Sobrien	     ??? They might be better written into the debug information.
193852558Sobrien	     This is possible when using DWARF.
193952558Sobrien
194052558Sobrien	     A language processor that wants static constants to be always
194152558Sobrien	     written out (even if it is not used) is responsible for
194252558Sobrien	     calling rest_of_decl_compilation itself.  E.g. the C front-end
194352558Sobrien	     calls rest_of_decl_compilation from finish_decl.
194452558Sobrien	     One motivation for this is that is conventional in some
194552558Sobrien	     environments to write things like:
194652558Sobrien	     static const char rcsid[] = "... version string ...";
194752558Sobrien	     intending to force the string to be in the executable.
194852558Sobrien
194952558Sobrien	     A language processor that would prefer to have unneeded
195052558Sobrien	     static constants "optimized away" would just defer writing
195152558Sobrien	     them out until here.  E.g. C++ does this, because static
195252558Sobrien	     constants are often defined in header files.
195352558Sobrien
195452558Sobrien	     ??? A tempting alternative (for both C and C++) would be
195552558Sobrien	     to force a constant to be written if and only if it is
195652558Sobrien	     defined in a main file, as opposed to an include file.  */
195752558Sobrien
195896289Sobrien	  if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
195952558Sobrien	    {
196096289Sobrien	      bool needed = 1;
196196289Sobrien
196296289Sobrien	      if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
196396289Sobrien		/* needed */;
196496289Sobrien	      else if (DECL_COMDAT (decl))
196596289Sobrien		needed = 0;
196696289Sobrien	      else if (TREE_READONLY (decl) && !TREE_PUBLIC (decl)
196796289Sobrien		       && (optimize || !flag_keep_static_consts
196896289Sobrien			   || DECL_ARTIFICIAL (decl)))
196996289Sobrien		needed = 0;
197096289Sobrien
197196289Sobrien	      if (needed)
197296289Sobrien		{
197396289Sobrien		  reconsider = 1;
197496289Sobrien		  rest_of_decl_compilation (decl, NULL, 1, 1);
197596289Sobrien		}
197652558Sobrien	    }
197752558Sobrien
197852558Sobrien	  if (TREE_CODE (decl) == FUNCTION_DECL
197952558Sobrien	      && DECL_INITIAL (decl) != 0
198052558Sobrien	      && DECL_SAVED_INSNS (decl) != 0
198152558Sobrien	      && (flag_keep_inline_functions
198252558Sobrien		  || (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
198352558Sobrien		  || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
198452558Sobrien	    {
198552558Sobrien	      reconsider = 1;
198652558Sobrien	      output_inline_function (decl);
198752558Sobrien	    }
198852558Sobrien	}
198952558Sobrien
199052558Sobrien      if (reconsider)
199152558Sobrien	output_something = 1;
199252558Sobrien    }
199352558Sobrien  while (reconsider);
199452558Sobrien
199552558Sobrien  return output_something;
199652558Sobrien}
199752558Sobrien
199852558Sobrien/* Issue appropriate warnings for the global declarations in VEC (of
199952558Sobrien   which there are LEN).  Output debugging information for them.  */
200090282Sobrien
200152558Sobrienvoid
200252558Sobriencheck_global_declarations (vec, len)
200352558Sobrien     tree *vec;
200452558Sobrien     int len;
200552558Sobrien{
200652558Sobrien  tree decl;
200752558Sobrien  int i;
200852558Sobrien
200952558Sobrien  for (i = 0; i < len; i++)
201052558Sobrien    {
201152558Sobrien      decl = vec[i];
201252558Sobrien
201352558Sobrien      if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)
201452558Sobrien	  && ! TREE_ASM_WRITTEN (decl))
201552558Sobrien	/* Cancel the RTL for this decl so that, if debugging info
201652558Sobrien	   output for global variables is still to come,
201752558Sobrien	   this one will be omitted.  */
201890282Sobrien	SET_DECL_RTL (decl, NULL_RTX);
201952558Sobrien
202052558Sobrien      /* Warn about any function
202152558Sobrien	 declared static but not defined.
202252558Sobrien	 We don't warn about variables,
202352558Sobrien	 because many programs have static variables
202452558Sobrien	 that exist only to get some text into the object file.  */
202552558Sobrien      if (TREE_CODE (decl) == FUNCTION_DECL
202690282Sobrien	  && (warn_unused_function
202752558Sobrien	      || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
202852558Sobrien	  && DECL_INITIAL (decl) == 0
202952558Sobrien	  && DECL_EXTERNAL (decl)
203052558Sobrien	  && ! DECL_ARTIFICIAL (decl)
203152558Sobrien	  && ! TREE_PUBLIC (decl))
203252558Sobrien	{
203352558Sobrien	  if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
203452558Sobrien	    pedwarn_with_decl (decl,
203552558Sobrien			       "`%s' used but never defined");
203652558Sobrien	  else
203752558Sobrien	    warning_with_decl (decl,
203852558Sobrien			       "`%s' declared `static' but never defined");
203952558Sobrien	  /* This symbol is effectively an "extern" declaration now.  */
204052558Sobrien	  TREE_PUBLIC (decl) = 1;
204152558Sobrien	  assemble_external (decl);
204252558Sobrien	}
204352558Sobrien
204452558Sobrien      /* Warn about static fns or vars defined but not used,
204552558Sobrien	 but not about inline functions or static consts
204652558Sobrien	 since defining those in header files is normal practice.  */
204790282Sobrien      if (((warn_unused_function
204890282Sobrien	    && TREE_CODE (decl) == FUNCTION_DECL && ! DECL_INLINE (decl))
204990282Sobrien	   || (warn_unused_variable
205090282Sobrien	       && TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
205152558Sobrien	  && ! DECL_IN_SYSTEM_HEADER (decl)
205252558Sobrien	  && ! DECL_EXTERNAL (decl)
205352558Sobrien	  && ! TREE_PUBLIC (decl)
205452558Sobrien	  && ! TREE_USED (decl)
205552558Sobrien	  && (TREE_CODE (decl) == FUNCTION_DECL || ! DECL_REGISTER (decl))
205652558Sobrien	  /* The TREE_USED bit for file-scope decls
205752558Sobrien	     is kept in the identifier, to handle multiple
205852558Sobrien	     external decls in different scopes.  */
205952558Sobrien	  && ! TREE_USED (DECL_NAME (decl)))
206052558Sobrien	warning_with_decl (decl, "`%s' defined but not used");
206152558Sobrien
206290282Sobrien      timevar_push (TV_SYMOUT);
206390282Sobrien      (*debug_hooks->global_decl) (decl);
206490282Sobrien      timevar_pop (TV_SYMOUT);
206552558Sobrien    }
206652558Sobrien}
206752558Sobrien
206890282Sobrien/* Save the current INPUT_FILENAME and LINENO on the top entry in the
206990282Sobrien   INPUT_FILE_STACK.  Push a new entry for FILE and LINE, and set the
207090282Sobrien   INPUT_FILENAME and LINENO accordingly.  */
207118334Speter
207290282Sobrienvoid
207390282Sobrienpush_srcloc (file, line)
207490282Sobrien     const char *file;
207590282Sobrien     int line;
207618334Speter{
207790282Sobrien  struct file_stack *fs;
207818334Speter
207990282Sobrien  if (input_file_stack)
208018334Speter    {
208190282Sobrien      input_file_stack->name = input_filename;
208290282Sobrien      input_file_stack->line = lineno;
208318334Speter    }
208418334Speter
208590282Sobrien  fs = (struct file_stack *) xmalloc (sizeof (struct file_stack));
208690282Sobrien  fs->name = input_filename = file;
208790282Sobrien  fs->line = lineno = line;
208890282Sobrien  fs->indent_level = 0;
208990282Sobrien  fs->next = input_file_stack;
209090282Sobrien  input_file_stack = fs;
209190282Sobrien  input_file_stack_tick++;
209290282Sobrien}
209318334Speter
209490282Sobrien/* Pop the top entry off the stack of presently open source files.
209590282Sobrien   Restore the INPUT_FILENAME and LINENO from the new topmost entry on
209690282Sobrien   the stack.  */
209718334Speter
209890282Sobrienvoid
209990282Sobrienpop_srcloc ()
210090282Sobrien{
210190282Sobrien  struct file_stack *fs;
210218334Speter
210390282Sobrien  fs = input_file_stack;
210490282Sobrien  input_file_stack = fs->next;
210590282Sobrien  free (fs);
210690282Sobrien  input_file_stack_tick++;
210790282Sobrien  /* The initial source file is never popped.  */
210890282Sobrien  if (!input_file_stack)
210990282Sobrien    abort ();
211090282Sobrien  input_filename = input_file_stack->name;
211190282Sobrien  lineno = input_file_stack->line;
211290282Sobrien}
211318334Speter
211490282Sobrien/* Compile an entire translation unit.  Write a file of assembly
211590282Sobrien   output and various debugging dumps.  */
211618334Speter
211790282Sobrienstatic void
211890282Sobriencompile_file ()
211990282Sobrien{
212090282Sobrien  tree globals;
212118334Speter
212218334Speter  /* Initialize yet another pass.  */
212318334Speter
212450615Sobrien  init_final (main_input_filename);
212550615Sobrien  init_branch_prob (dump_base_name);
212618334Speter
212790282Sobrien  timevar_push (TV_PARSE);
212818334Speter
212918334Speter  /* Call the parser, which parses the entire file
213018334Speter     (calling rest_of_compilation for each function).  */
213190282Sobrien  yyparse ();
213218334Speter
213390282Sobrien  /* In case there were missing block closers,
213490282Sobrien     get us back to the global binding level.  */
213590282Sobrien  (*lang_hooks.clear_binding_stack) ();
213618334Speter
213718334Speter  /* Compilation is now finished except for writing
213818334Speter     what's left of the symbol table output.  */
213918334Speter
214090282Sobrien  timevar_pop (TV_PARSE);
214118334Speter
214252558Sobrien  if (flag_syntax_only)
214390282Sobrien    return;
214452558Sobrien
214518334Speter  globals = getdecls ();
214618334Speter
214718334Speter  /* Really define vars that have had only a tentative definition.
214818334Speter     Really output inline functions that must actually be callable
214918334Speter     and have not been output so far.  */
215018334Speter
215118334Speter  {
215218334Speter    int len = list_length (globals);
215390282Sobrien    tree *vec = (tree *) xmalloc (sizeof (tree) * len);
215418334Speter    int i;
215518334Speter    tree decl;
215618334Speter
215718334Speter    /* Process the decls in reverse order--earliest first.
215818334Speter       Put them into VEC from back to front, then take out from front.  */
215918334Speter
216018334Speter    for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
216118334Speter      vec[len - i - 1] = decl;
216218334Speter
216352558Sobrien    wrapup_global_declarations (vec, len);
216418334Speter
216552558Sobrien    /* This must occur after the loop to output deferred functions.  Else
216652558Sobrien       the profiler initializer would not be emitted if all the functions
216752558Sobrien       in this compilation unit were deferred.
216818334Speter
216952558Sobrien       output_func_start_profiler can not cause any additional functions or
217052558Sobrien       data to need to be output, so it need not be in the deferred function
217152558Sobrien       loop above.  */
217252558Sobrien    output_func_start_profiler ();
217318334Speter
217490282Sobrien    check_global_declarations (vec, len);
217550615Sobrien
217690282Sobrien    /* Clean up.  */
217790282Sobrien    free (vec);
217818334Speter  }
217918334Speter
218018334Speter  /* Write out any pending weak symbol declarations.  */
218118334Speter
218218334Speter  weak_finish ();
218318334Speter
218490282Sobrien  /* Do dbx symbols.  */
218590282Sobrien  timevar_push (TV_SYMOUT);
218618334Speter
218750615Sobrien#ifdef DWARF2_UNWIND_INFO
218850615Sobrien  if (dwarf2out_do_frame ())
218950615Sobrien    dwarf2out_frame_finish ();
219050615Sobrien#endif
219150615Sobrien
219290282Sobrien  (*debug_hooks->finish) (main_input_filename);
219390282Sobrien  timevar_pop (TV_SYMOUT);
219450615Sobrien
219518334Speter  /* Output some stuff at end of file if nec.  */
219618334Speter
219790282Sobrien  dw2_output_indirect_constants ();
219890282Sobrien
219950615Sobrien  end_final (dump_base_name);
220018334Speter
220190282Sobrien  if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
220290282Sobrien    {
220390282Sobrien      timevar_push (TV_DUMP);
220490282Sobrien      open_dump_file (DFI_bp, NULL);
220552558Sobrien
220690282Sobrien      end_branch_prob ();
220718334Speter
220890282Sobrien      close_dump_file (DFI_bp, NULL, NULL_RTX);
220990282Sobrien      timevar_pop (TV_DUMP);
221018334Speter    }
221118334Speter
221290282Sobrien#ifdef ASM_FILE_END
221390282Sobrien  ASM_FILE_END (asm_out_file);
221490282Sobrien#endif
221518334Speter
221690282Sobrien  /* Attach a special .ident directive to the end of the file to identify
221790282Sobrien     the version of GCC which compiled this code.  The format of the .ident
221890282Sobrien     string is patterned after the ones produced by native SVR4 compilers.  */
221990282Sobrien#ifdef IDENT_ASM_OP
222090282Sobrien  if (!flag_no_ident)
222190282Sobrien    fprintf (asm_out_file, "%s\"GCC: (GNU) %s\"\n",
222290282Sobrien	     IDENT_ASM_OP, version_string);
222352558Sobrien#endif
222452558Sobrien
222590282Sobrien  if (optimize > 0 && open_dump_file (DFI_combine, NULL))
222618334Speter    {
222790282Sobrien      timevar_push (TV_DUMP);
222890282Sobrien      dump_combine_total_stats (rtl_dump_file);
222990282Sobrien      close_dump_file (DFI_combine, NULL, NULL_RTX);
223090282Sobrien      timevar_pop (TV_DUMP);
223118334Speter    }
223218334Speter}
223318334Speter
223418334Speter/* This is called from various places for FUNCTION_DECL, VAR_DECL,
223518334Speter   and TYPE_DECL nodes.
223618334Speter
223790282Sobrien   This does nothing for local (non-static) variables, unless the
223890282Sobrien   variable is a register variable with an ASMSPEC.  In that case, or
223990282Sobrien   if the variable is not an automatic, it sets up the RTL and
224090282Sobrien   outputs any assembler code (label definition, storage allocation
224190282Sobrien   and initialization).
224218334Speter
224318334Speter   DECL is the declaration.  If ASMSPEC is nonzero, it specifies
224418334Speter   the assembler symbol name to be used.  TOP_LEVEL is nonzero
224518334Speter   if this declaration is not within a function.  */
224618334Speter
224718334Spetervoid
224818334Speterrest_of_decl_compilation (decl, asmspec, top_level, at_end)
224918334Speter     tree decl;
225052558Sobrien     const char *asmspec;
225118334Speter     int top_level;
225218334Speter     int at_end;
225318334Speter{
225418334Speter  /* Declarations of variables, and of functions defined elsewhere.  */
225518334Speter
225618334Speter/* The most obvious approach, to put an #ifndef around where
225718334Speter   this macro is used, doesn't work since it's inside a macro call.  */
225818334Speter#ifndef ASM_FINISH_DECLARE_OBJECT
225918334Speter#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP, END)
226018334Speter#endif
226118334Speter
2262102796Skan  /* We deferred calling assemble_alias so that we could collect
2263102796Skan     other attributes such as visibility.  Emit the alias now.  */
2264102796Skan  {
2265102796Skan    tree alias;
2266102796Skan    alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
2267102796Skan    if (alias)
2268102796Skan      {
2269102796Skan	alias = TREE_VALUE (TREE_VALUE (alias));
2270102796Skan	alias = get_identifier (TREE_STRING_POINTER (alias));
2271102796Skan        assemble_alias (decl, alias);
2272102796Skan      }
2273102796Skan  }
2274102796Skan
227518334Speter  /* Forward declarations for nested functions are not "external",
227618334Speter     but we need to treat them as if they were.  */
227718334Speter  if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
227818334Speter      || TREE_CODE (decl) == FUNCTION_DECL)
227990282Sobrien    {
228090282Sobrien      timevar_push (TV_VARCONST);
228190282Sobrien      if (asmspec)
228290282Sobrien	make_decl_rtl (decl, asmspec);
228390282Sobrien      /* Don't output anything
228490282Sobrien	 when a tentative file-scope definition is seen.
228590282Sobrien	 But at end of compilation, do output code for them.  */
228690282Sobrien      if (at_end || !DECL_DEFER_OUTPUT (decl))
228790282Sobrien	assemble_variable (decl, top_level, at_end, 0);
228890282Sobrien      if (decl == last_assemble_variable_decl)
228990282Sobrien	{
229090282Sobrien	  ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
229190282Sobrien				     top_level, at_end);
229290282Sobrien	}
229390282Sobrien      timevar_pop (TV_VARCONST);
229490282Sobrien    }
229518334Speter  else if (DECL_REGISTER (decl) && asmspec != 0)
229618334Speter    {
229718334Speter      if (decode_reg_name (asmspec) >= 0)
229818334Speter	{
229990282Sobrien	  SET_DECL_RTL (decl, NULL_RTX);
230090282Sobrien	  make_decl_rtl (decl, asmspec);
230118334Speter	}
230218334Speter      else
230390282Sobrien	{
230490282Sobrien	  error ("invalid register name `%s' for register variable", asmspec);
230590282Sobrien	  DECL_REGISTER (decl) = 0;
230690282Sobrien	  if (!top_level)
230790282Sobrien	    expand_decl (decl);
230890282Sobrien	}
230918334Speter    }
231018334Speter#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
231118334Speter  else if ((write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
231218334Speter	   && TREE_CODE (decl) == TYPE_DECL)
231390282Sobrien    {
231490282Sobrien      timevar_push (TV_SYMOUT);
231590282Sobrien      dbxout_symbol (decl, 0);
231690282Sobrien      timevar_pop (TV_SYMOUT);
231790282Sobrien    }
231818334Speter#endif
231918334Speter#ifdef SDB_DEBUGGING_INFO
232018334Speter  else if (write_symbols == SDB_DEBUG && top_level
232118334Speter	   && TREE_CODE (decl) == TYPE_DECL)
232290282Sobrien    {
232390282Sobrien      timevar_push (TV_SYMOUT);
232490282Sobrien      sdbout_symbol (decl, 0);
232590282Sobrien      timevar_pop (TV_SYMOUT);
232690282Sobrien    }
232718334Speter#endif
232818334Speter}
232918334Speter
233018334Speter/* Called after finishing a record, union or enumeral type.  */
233118334Speter
233218334Spetervoid
233318334Speterrest_of_type_compilation (type, toplev)
233452558Sobrien#if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO) || defined (SDB_DEBUGGING_INFO)
233518334Speter     tree type;
233618334Speter     int toplev;
233752558Sobrien#else
233852558Sobrien     tree type ATTRIBUTE_UNUSED;
233952558Sobrien     int toplev ATTRIBUTE_UNUSED;
234052558Sobrien#endif
234118334Speter{
234290282Sobrien  timevar_push (TV_SYMOUT);
234318334Speter#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
234418334Speter  if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
234590282Sobrien    dbxout_symbol (TYPE_STUB_DECL (type), !toplev);
234618334Speter#endif
234718334Speter#ifdef SDB_DEBUGGING_INFO
234818334Speter  if (write_symbols == SDB_DEBUG)
234990282Sobrien    sdbout_symbol (TYPE_STUB_DECL (type), !toplev);
235018334Speter#endif
235190282Sobrien#ifdef DWARF2_DEBUGGING_INFO
235290282Sobrien  if ((write_symbols == DWARF2_DEBUG
235390282Sobrien       || write_symbols == VMS_AND_DWARF2_DEBUG)
235490282Sobrien      && toplev)
235590282Sobrien    dwarf2out_decl (TYPE_STUB_DECL (type));
235690282Sobrien#endif
235790282Sobrien  timevar_pop (TV_SYMOUT);
235818334Speter}
235918334Speter
236018334Speter/* This is called from finish_function (within yyparse)
236118334Speter   after each top-level definition is parsed.
236218334Speter   It is supposed to compile that function or variable
236318334Speter   and output the assembler code for it.
236418334Speter   After we return, the tree storage is freed.  */
236518334Speter
236618334Spetervoid
236718334Speterrest_of_compilation (decl)
236818334Speter     tree decl;
236918334Speter{
237090282Sobrien  rtx insns;
237118334Speter  int tem;
237218334Speter  int failure = 0;
237352558Sobrien  int rebuild_label_notes_after_reload;
237490282Sobrien  int register_life_up_to_date;
237596289Sobrien  int cleanup_crossjump;
237618334Speter
237790282Sobrien  timevar_push (TV_REST_OF_COMPILATION);
237890282Sobrien
237990282Sobrien  /* Now that we're out of the frontend, we shouldn't have any more
238090282Sobrien     CONCATs anywhere.  */
238190282Sobrien  generating_concat_p = 0;
238290282Sobrien
238390282Sobrien  /* When processing delayed functions, prepare_function_start() won't
238490282Sobrien     have been run to re-initialize it.  */
238590282Sobrien  cse_not_expected = ! optimize;
238690282Sobrien
238790282Sobrien  /* First, make sure that NOTE_BLOCK is set correctly for each
238890282Sobrien     NOTE_INSN_BLOCK_BEG/NOTE_INSN_BLOCK_END note.  */
238990282Sobrien  if (!cfun->x_whole_function_mode_p)
239090282Sobrien    identify_blocks ();
239190282Sobrien
239290282Sobrien  /* In function-at-a-time mode, we do not attempt to keep the BLOCK
239390282Sobrien     tree in sensible shape.  So, we just recalculate it here.  */
239490282Sobrien  if (cfun->x_whole_function_mode_p)
239590282Sobrien    reorder_blocks ();
239690282Sobrien
239790282Sobrien  init_flow ();
239890282Sobrien
239918334Speter  /* If we are reconsidering an inline function
240018334Speter     at the end of compilation, skip the stuff for making it inline.  */
240118334Speter
240218334Speter  if (DECL_SAVED_INSNS (decl) == 0)
240318334Speter    {
240450615Sobrien      int inlinable = 0;
240590282Sobrien      tree parent;
240652558Sobrien      const char *lose;
240718334Speter
240890282Sobrien      /* If this is nested inside an inlined external function, pretend
240990282Sobrien	 it was only declared.  Since we cannot inline such functions,
241090282Sobrien	 generating code for this one is not only not necessary but will
241190282Sobrien	 confuse some debugging output writers.  */
241290282Sobrien      for (parent = DECL_CONTEXT (current_function_decl);
241390282Sobrien	   parent != NULL_TREE;
241490282Sobrien	   parent = get_containing_scope (parent))
241590282Sobrien	if (TREE_CODE (parent) == FUNCTION_DECL
241690282Sobrien	    && DECL_INLINE (parent) && DECL_EXTERNAL (parent))
241790282Sobrien	  {
241890282Sobrien	    DECL_INITIAL (decl) = 0;
241990282Sobrien	    goto exit_rest_of_compilation;
242090282Sobrien	  }
242190282Sobrien
242218334Speter      /* If requested, consider whether to make this function inline.  */
242390282Sobrien      if ((DECL_INLINE (decl) && !flag_no_inline)
242490282Sobrien	  || flag_inline_functions)
242590282Sobrien	{
242690282Sobrien	  timevar_push (TV_INTEGRATION);
242790282Sobrien	  lose = function_cannot_inline_p (decl);
242890282Sobrien	  timevar_pop (TV_INTEGRATION);
242990282Sobrien	  if (lose || ! optimize)
243090282Sobrien	    {
243190282Sobrien	      if (warn_inline && DECL_INLINE (decl))
243290282Sobrien		warning_with_decl (decl, lose);
243390282Sobrien	      DECL_ABSTRACT_ORIGIN (decl) = 0;
243490282Sobrien	      /* Don't really compile an extern inline function.
243590282Sobrien		 If we can't make it inline, pretend
243690282Sobrien		 it was only declared.  */
243790282Sobrien	      if (DECL_EXTERNAL (decl))
243890282Sobrien		{
243990282Sobrien		  DECL_INITIAL (decl) = 0;
244090282Sobrien		  goto exit_rest_of_compilation;
244190282Sobrien		}
244290282Sobrien	    }
244390282Sobrien	  else
244490282Sobrien	    /* ??? Note that this has the effect of making it look
244590282Sobrien		 like "inline" was specified for a function if we choose
244690282Sobrien		 to inline it.  This isn't quite right, but it's
244790282Sobrien		 probably not worth the trouble to fix.  */
244890282Sobrien	    inlinable = DECL_INLINE (decl) = 1;
244990282Sobrien	}
245018334Speter
245118334Speter      insns = get_insns ();
245218334Speter
245318334Speter      /* Dump the rtl code if we are dumping rtl.  */
245418334Speter
245590282Sobrien      if (open_dump_file (DFI_rtl, decl))
245650615Sobrien	{
245750615Sobrien	  if (DECL_SAVED_INSNS (decl))
245850615Sobrien	    fprintf (rtl_dump_file, ";; (integrable)\n\n");
245990282Sobrien	  close_dump_file (DFI_rtl, print_rtl, insns);
246050615Sobrien	}
246118334Speter
246290282Sobrien      /* Convert from NOTE_INSN_EH_REGION style notes, and do other
246390282Sobrien	 sorts of eh initialization.  Delay this until after the
246490282Sobrien         initial rtl dump so that we can see the original nesting.  */
246590282Sobrien      convert_from_eh_region_ranges ();
246650615Sobrien
246718334Speter      /* If function is inline, and we don't yet know whether to
246818334Speter	 compile it by itself, defer decision till end of compilation.
246918334Speter	 finish_compilation will call rest_of_compilation again
247018334Speter	 for those functions that need to be output.  Also defer those
247190282Sobrien	 functions that we are supposed to defer.  */
247218334Speter
247390282Sobrien      if (inlinable
247490282Sobrien	  || (DECL_INLINE (decl)
247590282Sobrien	      && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)
247696289Sobrien		   && ! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
247790282Sobrien		   && ! flag_keep_inline_functions)
247890282Sobrien		  || DECL_EXTERNAL (decl))))
247990282Sobrien	DECL_DEFER_OUTPUT (decl) = 1;
248050615Sobrien
248190282Sobrien      if (DECL_INLINE (decl))
248290282Sobrien	/* DWARF wants separate debugging info for abstract and
248390282Sobrien	   concrete instances of all inline functions, including those
248490282Sobrien	   declared inline but not inlined, and those inlined even
248590282Sobrien	   though they weren't declared inline.  Conveniently, that's
248690282Sobrien	   what DECL_INLINE means at this point.  */
248790282Sobrien	(*debug_hooks->deferred_inline_function) (decl);
248890282Sobrien
248990282Sobrien      if (DECL_DEFER_OUTPUT (decl))
249050615Sobrien	{
249190282Sobrien	  /* If -Wreturn-type, we have to do a bit of compilation.  We just
249290282Sobrien	     want to call cleanup the cfg to figure out whether or not we can
249390282Sobrien	     fall off the end of the function; we do the minimum amount of
249490282Sobrien	     work necessary to make that safe.  */
249550615Sobrien	  if (warn_return_type)
249618334Speter	    {
249750615Sobrien	      int saved_optimize = optimize;
249890282Sobrien
249950615Sobrien	      optimize = 0;
250090282Sobrien	      rebuild_jump_labels (insns);
250150615Sobrien	      find_exception_handler_labels ();
250290282Sobrien	      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
250390282Sobrien	      cleanup_cfg (CLEANUP_PRE_SIBCALL | CLEANUP_PRE_LOOP);
250450615Sobrien	      optimize = saved_optimize;
250590282Sobrien
250690282Sobrien	      /* CFG is no longer maintained up-to-date.  */
250790282Sobrien	      free_bb_for_insn ();
250850615Sobrien	    }
250950615Sobrien
251090282Sobrien	  current_function_nothrow = nothrow_function_p ();
251190282Sobrien	  if (current_function_nothrow)
251290282Sobrien	    /* Now we know that this can't throw; set the flag for the benefit
251390282Sobrien	       of other functions later in this translation unit.  */
251490282Sobrien	    TREE_NOTHROW (current_function_decl) = 1;
251590282Sobrien
251690282Sobrien	  timevar_push (TV_INTEGRATION);
251790282Sobrien	  save_for_inline (decl);
251890282Sobrien	  timevar_pop (TV_INTEGRATION);
251990282Sobrien	  DECL_SAVED_INSNS (decl)->inlinable = inlinable;
252050615Sobrien	  goto exit_rest_of_compilation;
252118334Speter	}
252218334Speter
252318334Speter      /* If specified extern inline but we aren't inlining it, we are
252452558Sobrien	 done.  This goes for anything that gets here with DECL_EXTERNAL
252552558Sobrien	 set, not just things with DECL_INLINE.  */
252652558Sobrien      if (DECL_EXTERNAL (decl))
252718334Speter	goto exit_rest_of_compilation;
252818334Speter    }
252918334Speter
253090282Sobrien  /* If we're emitting a nested function, make sure its parent gets
253190282Sobrien     emitted as well.  Doing otherwise confuses debug info.  */
253290282Sobrien  {
253390282Sobrien    tree parent;
253490282Sobrien    for (parent = DECL_CONTEXT (current_function_decl);
253590282Sobrien	 parent != NULL_TREE;
253690282Sobrien	 parent = get_containing_scope (parent))
253790282Sobrien      if (TREE_CODE (parent) == FUNCTION_DECL)
253890282Sobrien	TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (parent)) = 1;
253990282Sobrien  }
254090282Sobrien
254190282Sobrien  /* We are now committed to emitting code for this function.  Do any
254290282Sobrien     preparation, such as emitting abstract debug info for the inline
254390282Sobrien     before it gets mangled by optimization.  */
254490282Sobrien  if (DECL_INLINE (decl))
254590282Sobrien    (*debug_hooks->outlining_inline_function) (decl);
254690282Sobrien
254790282Sobrien  /* Remove any notes we don't need.  That will make iterating
254890282Sobrien     over the instruction sequence faster, and allow the garbage
254990282Sobrien     collector to reclaim the memory used by the notes.  */
255090282Sobrien  remove_unnecessary_notes ();
255190282Sobrien  reorder_blocks ();
255290282Sobrien
255390282Sobrien  ggc_collect ();
255490282Sobrien
255590282Sobrien  /* Initialize some variables used by the optimizers.  */
255690282Sobrien  init_function_for_compilation ();
255790282Sobrien
255818334Speter  if (! DECL_DEFER_OUTPUT (decl))
255918334Speter    TREE_ASM_WRITTEN (decl) = 1;
256018334Speter
256190282Sobrien  /* Now that integrate will no longer see our rtl, we need not
256290282Sobrien     distinguish between the return value of this function and the
256390282Sobrien     return value of called functions.  Also, we can remove all SETs
256490282Sobrien     of subregs of hard registers; they are only here because of
256590282Sobrien     integrate.  Also, we can now initialize pseudos intended to
256690282Sobrien     carry magic hard reg data throughout the function.  */
256718334Speter  rtx_equal_function_value_matters = 0;
256890282Sobrien  purge_hard_subreg_sets (get_insns ());
256918334Speter
257096289Sobrien  /* Early return if there were errors.  We can run afoul of our
257196289Sobrien     consistency checks, and there's not really much point in fixing them.
257296289Sobrien     Don't return yet if -Wreturn-type; we need to do cleanup_cfg.  */
257396289Sobrien  if (((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type)
257496289Sobrien      || errorcount || sorrycount)
257590282Sobrien    goto exit_rest_of_compilation;
257690282Sobrien
257790282Sobrien  /* We may have potential sibling or tail recursion sites.  Select one
257890282Sobrien     (of possibly multiple) methods of performing the call.  */
257990282Sobrien  if (flag_optimize_sibling_calls)
258018334Speter    {
258190282Sobrien      timevar_push (TV_JUMP);
258290282Sobrien      open_dump_file (DFI_sibling, decl);
258390282Sobrien
258490282Sobrien      optimize_sibling_and_tail_recursive_calls ();
258590282Sobrien
258690282Sobrien      close_dump_file (DFI_sibling, print_rtl, get_insns ());
258790282Sobrien      timevar_pop (TV_JUMP);
258818334Speter    }
258918334Speter
259090282Sobrien  /* Complete generation of exception handling code.  */
259190282Sobrien  find_exception_handler_labels ();
259290282Sobrien  if (doing_eh (0))
259390282Sobrien    {
259490282Sobrien      timevar_push (TV_JUMP);
259590282Sobrien      open_dump_file (DFI_eh, decl);
259618334Speter
259790282Sobrien      finish_eh_generation ();
259890282Sobrien
259990282Sobrien      close_dump_file (DFI_eh, print_rtl, get_insns ());
260090282Sobrien      timevar_pop (TV_JUMP);
260190282Sobrien    }
260290282Sobrien
260396289Sobrien  /* Delay emitting hard_reg_initial_value sets until after EH landing pad
260496289Sobrien     generation, which might create new sets.  */
260596289Sobrien  emit_initial_value_sets ();
260696289Sobrien
260718334Speter#ifdef FINALIZE_PIC
260818334Speter  /* If we are doing position-independent code generation, now
260918334Speter     is the time to output special prologues and epilogues.
261018334Speter     We do not want to do this earlier, because it just clutters
261118334Speter     up inline functions with meaningless insns.  */
261218334Speter  if (flag_pic)
261318334Speter    FINALIZE_PIC;
261418334Speter#endif
261518334Speter
261618334Speter  insns = get_insns ();
261718334Speter
261818334Speter  /* Copy any shared structure that should not be shared.  */
261972566Sobrien  unshare_all_rtl (current_function_decl, insns);
262018334Speter
262150615Sobrien#ifdef SETJMP_VIA_SAVE_AREA
262290282Sobrien  /* This must be performed before virtual register instantiation.  */
262350615Sobrien  if (current_function_calls_alloca)
262450615Sobrien    optimize_save_area_alloca (insns);
262550615Sobrien#endif
262650615Sobrien
262718334Speter  /* Instantiate all virtual registers.  */
262890282Sobrien  instantiate_virtual_regs (current_function_decl, insns);
262918334Speter
263090282Sobrien  open_dump_file (DFI_jump, decl);
263118334Speter
263250615Sobrien  /* Always do one jump optimization pass to ensure that JUMP_LABEL fields
263350615Sobrien     are initialized and to compute whether control can drop off the end
263450615Sobrien     of the function.  */
263518334Speter
263690282Sobrien  timevar_push (TV_JUMP);
263790282Sobrien  /* Turn NOTE_INSN_EXPECTED_VALUE into REG_BR_PROB.  Do this
263890282Sobrien     before jump optimization switches branch directions.  */
263990282Sobrien  expected_value_to_br_prob ();
264090282Sobrien
264190282Sobrien  reg_scan (insns, max_reg_num (), 0);
264290282Sobrien  rebuild_jump_labels (insns);
264390282Sobrien  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
264490282Sobrien  cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP);
264590282Sobrien
264690282Sobrien  /* CFG is no longer maintained up-to-date.  */
264790282Sobrien  free_bb_for_insn ();
264890282Sobrien  copy_loop_headers (insns);
264990282Sobrien  purge_line_number_notes (insns);
265090282Sobrien
265190282Sobrien  timevar_pop (TV_JUMP);
265290282Sobrien
265318334Speter  /* Now is when we stop if -fsyntax-only and -Wreturn-type.  */
265418334Speter  if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl))
265590282Sobrien    {
265690282Sobrien      close_dump_file (DFI_jump, print_rtl, insns);
265790282Sobrien      goto exit_rest_of_compilation;
265890282Sobrien    }
265918334Speter
266090282Sobrien  /* Long term, this should probably move before the jump optimizer too,
266190282Sobrien     but I didn't want to disturb the rtl_dump_and_exit and related
266290282Sobrien     stuff at this time.  */
266390282Sobrien  if (optimize > 0 && flag_ssa)
266490282Sobrien    {
266590282Sobrien      /* Convert to SSA form.  */
266618334Speter
266790282Sobrien      timevar_push (TV_TO_SSA);
266890282Sobrien      open_dump_file (DFI_ssa, decl);
266918334Speter
267090282Sobrien      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
267190282Sobrien      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
267290282Sobrien      convert_to_ssa ();
267390282Sobrien
267490282Sobrien      close_dump_file (DFI_ssa, print_rtl_with_bb, insns);
267590282Sobrien      timevar_pop (TV_TO_SSA);
267690282Sobrien
267790282Sobrien      /* Perform sparse conditional constant propagation, if requested.  */
267890282Sobrien      if (flag_ssa_ccp)
267990282Sobrien	{
268090282Sobrien	  timevar_push (TV_SSA_CCP);
268190282Sobrien	  open_dump_file (DFI_ssa_ccp, decl);
268290282Sobrien
268390282Sobrien	  ssa_const_prop ();
268490282Sobrien
268590282Sobrien	  close_dump_file (DFI_ssa_ccp, print_rtl_with_bb, get_insns ());
268690282Sobrien	  timevar_pop (TV_SSA_CCP);
268790282Sobrien	}
268890282Sobrien
268990282Sobrien      /* It would be useful to cleanup the CFG at this point, but block
269090282Sobrien	 merging and possibly other transformations might leave a PHI
269190282Sobrien	 node in the middle of a basic block, which is a strict no-no.  */
269290282Sobrien
269390282Sobrien      /* The SSA implementation uses basic block numbers in its phi
269490282Sobrien	 nodes.  Thus, changing the control-flow graph or the basic
269590282Sobrien	 blocks, e.g., calling find_basic_blocks () or cleanup_cfg (),
269690282Sobrien	 may cause problems.  */
269790282Sobrien
269890282Sobrien      if (flag_ssa_dce)
269990282Sobrien	{
270090282Sobrien	  /* Remove dead code.  */
270190282Sobrien
270290282Sobrien	  timevar_push (TV_SSA_DCE);
270390282Sobrien	  open_dump_file (DFI_ssa_dce, decl);
270490282Sobrien
270590282Sobrien	  insns = get_insns ();
270690282Sobrien	  ssa_eliminate_dead_code();
270790282Sobrien
270890282Sobrien	  close_dump_file (DFI_ssa_dce, print_rtl_with_bb, insns);
270990282Sobrien	  timevar_pop (TV_SSA_DCE);
271090282Sobrien	}
271190282Sobrien
271290282Sobrien      /* Convert from SSA form.  */
271390282Sobrien
271490282Sobrien      timevar_push (TV_FROM_SSA);
271590282Sobrien      open_dump_file (DFI_ussa, decl);
271690282Sobrien
271790282Sobrien      convert_from_ssa ();
271890282Sobrien      /* New registers have been created.  Rescan their usage.  */
271990282Sobrien      reg_scan (insns, max_reg_num (), 1);
272090282Sobrien
272190282Sobrien      close_dump_file (DFI_ussa, print_rtl_with_bb, insns);
272290282Sobrien      timevar_pop (TV_FROM_SSA);
272390282Sobrien
272490282Sobrien      ggc_collect ();
272590282Sobrien      /* CFG is no longer maintained up-to-date.  */
272690282Sobrien      free_bb_for_insn ();
272790282Sobrien    }
272890282Sobrien
272990282Sobrien  timevar_push (TV_JUMP);
273090282Sobrien
273190282Sobrien  if (optimize > 0)
273290282Sobrien    {
273390282Sobrien      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
273490282Sobrien      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP
273590282Sobrien 		   | (flag_thread_jumps ? CLEANUP_THREADING : 0));
273690282Sobrien
273790282Sobrien      /* ??? Run if-conversion before delete_null_pointer_checks,
273890282Sobrien         since the later does not preserve the CFG.  This should
273990282Sobrien	 be changed -- no since converting if's that are going to
274090282Sobrien	 be deleted.  */
274190282Sobrien      timevar_push (TV_IFCVT);
274290282Sobrien      if_convert (0);
274390282Sobrien      timevar_pop (TV_IFCVT);
274490282Sobrien
274590282Sobrien      /* CFG is no longer maintained up-to-date.  */
274690282Sobrien      free_bb_for_insn ();
274790282Sobrien      /* Try to identify useless null pointer tests and delete them.  */
274890282Sobrien      if (flag_delete_null_pointer_checks)
274990282Sobrien	delete_null_pointer_checks (insns);
275090282Sobrien    }
275190282Sobrien
275290282Sobrien  /* Jump optimization, and the removal of NULL pointer checks, may
275390282Sobrien     have reduced the number of instructions substantially.  CSE, and
275490282Sobrien     future passes, allocate arrays whose dimensions involve the
275590282Sobrien     maximum instruction UID, so if we can reduce the maximum UID
275690282Sobrien     we'll save big on memory.  */
275790282Sobrien  renumber_insns (rtl_dump_file);
275890282Sobrien  timevar_pop (TV_JUMP);
275990282Sobrien
276090282Sobrien  close_dump_file (DFI_jump, print_rtl, insns);
276190282Sobrien
276290282Sobrien  ggc_collect ();
276390282Sobrien
276418334Speter  /* Perform common subexpression elimination.
276518334Speter     Nonzero value from `cse_main' means that jumps were simplified
276618334Speter     and some code may now be unreachable, so do
276718334Speter     jump optimization again.  */
276818334Speter
276918334Speter  if (optimize > 0)
277018334Speter    {
277190282Sobrien      open_dump_file (DFI_cse, decl);
277290282Sobrien      timevar_push (TV_CSE);
277350615Sobrien
277490282Sobrien      reg_scan (insns, max_reg_num (), 1);
277518334Speter
277690282Sobrien      tem = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
277718334Speter
277890282Sobrien      /* If we are not running more CSE passes, then we are no longer
277990282Sobrien	 expecting CSE to be run.  But always rerun it in a cheap mode.  */
278090282Sobrien      cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse;
278190282Sobrien
278218334Speter      if (tem || optimize > 1)
278390282Sobrien	{
278490282Sobrien	  timevar_push (TV_JUMP);
278590282Sobrien	  rebuild_jump_labels (insns);
278690282Sobrien	  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
278790282Sobrien	  cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
278890282Sobrien	  timevar_pop (TV_JUMP);
278990282Sobrien	  /* CFG is no longer maintained up-to-date.  */
279090282Sobrien	  free_bb_for_insn ();
279190282Sobrien	}
279250615Sobrien
279356392Sobrien      /* Run this after jump optmizations remove all the unreachable code
279456392Sobrien	 so that unreachable code will not keep values live.  */
279590282Sobrien      delete_trivially_dead_insns (insns, max_reg_num (), 0);
279656392Sobrien
279790282Sobrien      /* Try to identify useless null pointer tests and delete them.  */
279890282Sobrien      if (flag_delete_null_pointer_checks || flag_thread_jumps)
279990282Sobrien	{
280090282Sobrien	  timevar_push (TV_JUMP);
280190282Sobrien	  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
280252558Sobrien
280390282Sobrien	  cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP
280490282Sobrien		       | (flag_thread_jumps ? CLEANUP_THREADING : 0));
280590282Sobrien
280690282Sobrien	  if (flag_delete_null_pointer_checks)
280790282Sobrien	    delete_null_pointer_checks (insns);
280890282Sobrien	  /* CFG is no longer maintained up-to-date.  */
280990282Sobrien	  free_bb_for_insn ();
281090282Sobrien	  timevar_pop (TV_JUMP);
281152558Sobrien	}
281290282Sobrien
281390282Sobrien      /* The second pass of jump optimization is likely to have
281490282Sobrien         removed a bunch more instructions.  */
281590282Sobrien      renumber_insns (rtl_dump_file);
281690282Sobrien
281790282Sobrien      timevar_pop (TV_CSE);
281890282Sobrien      close_dump_file (DFI_cse, print_rtl, insns);
281918334Speter    }
282018334Speter
282190282Sobrien  open_dump_file (DFI_addressof, decl);
282290282Sobrien
282350615Sobrien  purge_addressof (insns);
282450615Sobrien  reg_scan (insns, max_reg_num (), 1);
282518334Speter
282690282Sobrien  close_dump_file (DFI_addressof, print_rtl, insns);
282752558Sobrien
282890282Sobrien  ggc_collect ();
282990282Sobrien
283050615Sobrien  /* Perform global cse.  */
283118334Speter
283250615Sobrien  if (optimize > 0 && flag_gcse)
283350615Sobrien    {
283490282Sobrien      int save_csb, save_cfj;
283590282Sobrien      int tem2 = 0;
283618334Speter
283790282Sobrien      timevar_push (TV_GCSE);
283890282Sobrien      open_dump_file (DFI_gcse, decl);
283952558Sobrien
284090282Sobrien      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
284190282Sobrien      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
284290282Sobrien      tem = gcse_main (insns, rtl_dump_file);
284390282Sobrien      rebuild_jump_labels (insns);
284490282Sobrien
284590282Sobrien      save_csb = flag_cse_skip_blocks;
284690282Sobrien      save_cfj = flag_cse_follow_jumps;
284790282Sobrien      flag_cse_skip_blocks = flag_cse_follow_jumps = 0;
284890282Sobrien
284990282Sobrien      /* CFG is no longer maintained up-to-date.  */
285090282Sobrien      free_bb_for_insn ();
285190282Sobrien      /* If -fexpensive-optimizations, re-run CSE to clean up things done
285290282Sobrien	 by gcse.  */
285390282Sobrien      if (flag_expensive_optimizations)
285452558Sobrien	{
285590282Sobrien	  timevar_push (TV_CSE);
285690282Sobrien	  reg_scan (insns, max_reg_num (), 1);
285790282Sobrien	  tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
285890282Sobrien	  timevar_pop (TV_CSE);
285990282Sobrien	  cse_not_expected = !flag_rerun_cse_after_loop;
286090282Sobrien	}
286152558Sobrien
286290282Sobrien      /* If gcse or cse altered any jumps, rerun jump optimizations to clean
286390282Sobrien	 things up.  Then possibly re-run CSE again.  */
286490282Sobrien      while (tem || tem2)
286552558Sobrien	{
286690282Sobrien	  tem = tem2 = 0;
286790282Sobrien	  timevar_push (TV_JUMP);
286890282Sobrien	  rebuild_jump_labels (insns);
286990282Sobrien	  delete_trivially_dead_insns (insns, max_reg_num (), 0);
287090282Sobrien	  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
287190282Sobrien	  cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
287290282Sobrien	  /* CFG is no longer maintained up-to-date.  */
287390282Sobrien	  free_bb_for_insn ();
287490282Sobrien	  timevar_pop (TV_JUMP);
287590282Sobrien
287690282Sobrien	  if (flag_expensive_optimizations)
287790282Sobrien	    {
287890282Sobrien	      timevar_push (TV_CSE);
287990282Sobrien	      reg_scan (insns, max_reg_num (), 1);
288090282Sobrien	      tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
288190282Sobrien	      timevar_pop (TV_CSE);
288290282Sobrien	    }
288352558Sobrien	}
288490282Sobrien
288590282Sobrien      close_dump_file (DFI_gcse, print_rtl, insns);
288690282Sobrien      timevar_pop (TV_GCSE);
288790282Sobrien
288890282Sobrien      ggc_collect ();
288990282Sobrien      flag_cse_skip_blocks = save_csb;
289090282Sobrien      flag_cse_follow_jumps = save_cfj;
289150615Sobrien    }
289290282Sobrien
289318334Speter  /* Move constant computations out of loops.  */
289418334Speter
289518334Speter  if (optimize > 0)
289618334Speter    {
289790282Sobrien      timevar_push (TV_LOOP);
289890282Sobrien      open_dump_file (DFI_loop, decl);
289990282Sobrien      free_bb_for_insn ();
290018334Speter
290190282Sobrien      if (flag_rerun_loop_opt)
290290282Sobrien	{
290390282Sobrien	  cleanup_barriers ();
290490282Sobrien
290590282Sobrien	  /* We only want to perform unrolling once.  */
290696289Sobrien	  loop_optimize (insns, rtl_dump_file, LOOP_FIRST_PASS);
290790282Sobrien
290890282Sobrien	  /* The first call to loop_optimize makes some instructions
290990282Sobrien	     trivially dead.  We delete those instructions now in the
291090282Sobrien	     hope that doing so will make the heuristics in loop work
291190282Sobrien	     better and possibly speed up compilation.  */
291290282Sobrien	  delete_trivially_dead_insns (insns, max_reg_num (), 0);
291390282Sobrien
291490282Sobrien	  /* The regscan pass is currently necessary as the alias
291550615Sobrien		  analysis code depends on this information.  */
291690282Sobrien	  reg_scan (insns, max_reg_num (), 1);
291790282Sobrien	}
291890282Sobrien      cleanup_barriers ();
291990282Sobrien      loop_optimize (insns, rtl_dump_file,
292090282Sobrien		     (flag_unroll_loops ? LOOP_UNROLL : 0) | LOOP_BCT
292190282Sobrien		     | (flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0));
292252558Sobrien
292390282Sobrien      close_dump_file (DFI_loop, print_rtl, insns);
292490282Sobrien      timevar_pop (TV_LOOP);
292552558Sobrien
292690282Sobrien      ggc_collect ();
292750615Sobrien    }
292818334Speter
292950615Sobrien  if (optimize > 0)
293018334Speter    {
293190282Sobrien      timevar_push (TV_CSE2);
293290282Sobrien      open_dump_file (DFI_cse2, decl);
293352558Sobrien
293450615Sobrien      if (flag_rerun_cse_after_loop)
293550615Sobrien	{
293650615Sobrien	  /* Running another jump optimization pass before the second
293750615Sobrien	     cse pass sometimes simplifies the RTL enough to allow
293850615Sobrien	     the second CSE pass to do a better job.  Jump_optimize can change
293950615Sobrien	     max_reg_num so we must rerun reg_scan afterwards.
294050615Sobrien	     ??? Rework to not call reg_scan so often.  */
294190282Sobrien	  timevar_push (TV_JUMP);
294290282Sobrien
294390282Sobrien	  /* The previous call to loop_optimize makes some instructions
294490282Sobrien	     trivially dead.  We delete those instructions now in the
294590282Sobrien	     hope that doing so will make the heuristics in jump work
294690282Sobrien	     better and possibly speed up compilation.  */
294790282Sobrien	  delete_trivially_dead_insns (insns, max_reg_num (), 0);
294890282Sobrien
294990282Sobrien	  reg_scan (insns, max_reg_num (), 0);
295090282Sobrien
295190282Sobrien	  timevar_push (TV_IFCVT);
295290282Sobrien
295390282Sobrien	  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
295490282Sobrien	  cleanup_cfg (CLEANUP_EXPENSIVE);
295590282Sobrien	  if_convert (0);
295690282Sobrien
295790282Sobrien	  timevar_pop(TV_IFCVT);
295890282Sobrien
295990282Sobrien	  timevar_pop (TV_JUMP);
296090282Sobrien
296190282Sobrien	  /* CFG is no longer maintained up-to-date.  */
296290282Sobrien	  free_bb_for_insn ();
296390282Sobrien	  reg_scan (insns, max_reg_num (), 0);
296490282Sobrien	  tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file);
296590282Sobrien
296650615Sobrien	  if (tem)
296790282Sobrien	    {
296890282Sobrien	      timevar_push (TV_JUMP);
296990282Sobrien	      rebuild_jump_labels (insns);
297090282Sobrien	      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
297190282Sobrien	      cleanup_cfg (CLEANUP_EXPENSIVE);
297290282Sobrien	      /* CFG is no longer maintained up-to-date.  */
297390282Sobrien	      free_bb_for_insn ();
297490282Sobrien	      timevar_pop (TV_JUMP);
297590282Sobrien	    }
297650615Sobrien	}
297718334Speter
297890282Sobrien      close_dump_file (DFI_cse2, print_rtl, insns);
297990282Sobrien      timevar_pop (TV_CSE2);
298052558Sobrien
298190282Sobrien      ggc_collect ();
298218334Speter    }
298352558Sobrien
298490282Sobrien  cse_not_expected = 1;
298590282Sobrien
298690282Sobrien  regclass_init ();
298790282Sobrien
298890282Sobrien  /* Do control and data flow analysis; wrote some of the results to
298990282Sobrien     the dump file.  */
299090282Sobrien
299190282Sobrien  timevar_push (TV_FLOW);
299290282Sobrien  open_dump_file (DFI_cfg, decl);
299390282Sobrien
299490282Sobrien  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
299590282Sobrien  cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0)
299690282Sobrien	       | (flag_thread_jumps ? CLEANUP_THREADING : 0));
299790282Sobrien  check_function_return_warnings ();
299890282Sobrien
299990282Sobrien  /* It may make more sense to mark constant functions after dead code is
300090282Sobrien     eliminated by life_analyzis, but we need to do it early, as -fprofile-arcs
300190282Sobrien     may insert code making function non-constant, but we still must consider
300290282Sobrien     it as constant, otherwise -fbranch-probabilities will not read data back.
300390282Sobrien
300490282Sobrien     life_analyzis rarely eliminates modification of external memory.
300590282Sobrien   */
300690282Sobrien  mark_constant_function ();
300790282Sobrien
300890282Sobrien  close_dump_file (DFI_cfg, print_rtl_with_bb, insns);
300990282Sobrien
301050615Sobrien  if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
301150615Sobrien    {
301290282Sobrien      timevar_push (TV_BRANCH_PROB);
301390282Sobrien      open_dump_file (DFI_bp, decl);
301452558Sobrien
301590282Sobrien      branch_prob ();
301652558Sobrien
301790282Sobrien      close_dump_file (DFI_bp, print_rtl_with_bb, insns);
301890282Sobrien      timevar_pop (TV_BRANCH_PROB);
301950615Sobrien    }
302052558Sobrien
302190282Sobrien  open_dump_file (DFI_life, decl);
302290282Sobrien  if (optimize)
302390282Sobrien    {
302490282Sobrien      struct loops loops;
302518334Speter
302690282Sobrien      /* Discover and record the loop depth at the head of each basic
302790282Sobrien	 block.  The loop infrastructure does the real job for us.  */
302890282Sobrien      flow_loops_find (&loops, LOOP_TREE);
302918334Speter
3030104765Skan      if (rtl_dump_file)
3031104765Skan	flow_loops_dump (&loops, rtl_dump_file, NULL, 0);
3032104765Skan
303390282Sobrien      /* Estimate using heuristics if no profiling info is available.  */
303490282Sobrien      if (flag_guess_branch_prob)
303590282Sobrien	estimate_probability (&loops);
303618334Speter
303790282Sobrien      flow_loops_free (&loops);
303890282Sobrien    }
303990282Sobrien  life_analysis (insns, rtl_dump_file, PROP_FINAL);
304090282Sobrien  timevar_pop (TV_FLOW);
304118334Speter
304290282Sobrien  no_new_pseudos = 1;
304318334Speter
304490282Sobrien  if (warn_uninitialized || extra_warnings)
304518334Speter    {
304690282Sobrien      uninitialized_vars_warning (DECL_INITIAL (decl));
304790282Sobrien      if (extra_warnings)
304890282Sobrien	setjmp_args_warning ();
304918334Speter    }
305090282Sobrien
305190282Sobrien  if (optimize)
305218334Speter    {
305390282Sobrien      if (initialize_uninitialized_subregs ())
305418334Speter	{
305590282Sobrien	  /* Insns were inserted, so things might look a bit different.  */
305690282Sobrien	  insns = get_insns ();
305790282Sobrien	  life_analysis (insns, rtl_dump_file,
305890282Sobrien			 (PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES));
305918334Speter	}
306018334Speter    }
306118334Speter
306290282Sobrien  close_dump_file (DFI_life, print_rtl_with_bb, insns);
306318334Speter
306490282Sobrien  ggc_collect ();
306552558Sobrien
306618334Speter  /* If -opt, try combining insns through substitution.  */
306718334Speter
306818334Speter  if (optimize > 0)
306950615Sobrien    {
307090282Sobrien      int rebuild_jump_labels_after_combine = 0;
307152558Sobrien
307290282Sobrien      timevar_push (TV_COMBINE);
307390282Sobrien      open_dump_file (DFI_combine, decl);
307452558Sobrien
307590282Sobrien      rebuild_jump_labels_after_combine
307690282Sobrien	= combine_instructions (insns, max_reg_num ());
307790282Sobrien
307890282Sobrien      /* Always purge dead edges, as we may eliminate an insn throwing
307990282Sobrien         exception.  */
308090282Sobrien      rebuild_jump_labels_after_combine |= purge_all_dead_edges (true);
308190282Sobrien
308290282Sobrien      /* Combining insns may have turned an indirect jump into a
308390282Sobrien	 direct jump.  Rebuid the JUMP_LABEL fields of jumping
308490282Sobrien	 instructions.  */
308590282Sobrien      if (rebuild_jump_labels_after_combine)
308652558Sobrien	{
308790282Sobrien	  timevar_push (TV_JUMP);
308890282Sobrien	  rebuild_jump_labels (insns);
308990282Sobrien	  timevar_pop (TV_JUMP);
309090282Sobrien
309190282Sobrien	  cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE);
309252558Sobrien	}
309390282Sobrien
309490282Sobrien      close_dump_file (DFI_combine, print_rtl_with_bb, insns);
309590282Sobrien      timevar_pop (TV_COMBINE);
309690282Sobrien
309790282Sobrien      ggc_collect ();
309850615Sobrien    }
309918334Speter
310090282Sobrien  /* Rerun if-conversion, as combine may have simplified things enough to
310190282Sobrien     now meet sequence length restrictions.  */
310290282Sobrien  if (optimize > 0)
310390282Sobrien    {
310490282Sobrien      timevar_push (TV_IFCVT);
310590282Sobrien      open_dump_file (DFI_ce, decl);
310690282Sobrien
310790282Sobrien      no_new_pseudos = 0;
310890282Sobrien      if_convert (1);
310990282Sobrien      no_new_pseudos = 1;
311090282Sobrien
311190282Sobrien      close_dump_file (DFI_ce, print_rtl_with_bb, insns);
311290282Sobrien      timevar_pop (TV_IFCVT);
311390282Sobrien    }
311490282Sobrien
311550615Sobrien  /* Register allocation pre-pass, to reduce number of moves
311650615Sobrien     necessary for two-address machines.  */
311750615Sobrien  if (optimize > 0 && (flag_regmove || flag_expensive_optimizations))
311850615Sobrien    {
311990282Sobrien      timevar_push (TV_REGMOVE);
312090282Sobrien      open_dump_file (DFI_regmove, decl);
312152558Sobrien
312290282Sobrien      regmove_optimize (insns, max_reg_num (), rtl_dump_file);
312352558Sobrien
312490282Sobrien      close_dump_file (DFI_regmove, print_rtl_with_bb, insns);
312590282Sobrien      timevar_pop (TV_REGMOVE);
312690282Sobrien
312790282Sobrien      ggc_collect ();
312850615Sobrien    }
312918334Speter
313090282Sobrien  /* Do unconditional splitting before register allocation to allow machine
313190282Sobrien     description to add extra information not needed previously.  */
313290282Sobrien  split_all_insns (1);
313390282Sobrien
313490282Sobrien  /* Any of the several passes since flow1 will have munged register
313590282Sobrien     lifetime data a bit.  */
313690282Sobrien  register_life_up_to_date = 0;
313790282Sobrien
313890282Sobrien#ifdef OPTIMIZE_MODE_SWITCHING
313990282Sobrien  timevar_push (TV_MODE_SWITCH);
314090282Sobrien
314190282Sobrien  no_new_pseudos = 0;
314290282Sobrien  if (optimize_mode_switching (NULL))
314390282Sobrien    {
314490282Sobrien      /* We did work, and so had to regenerate global life information.
314590282Sobrien	 Take advantage of this and don't re-recompute register life
314690282Sobrien	 information below.  */
314790282Sobrien      register_life_up_to_date = 1;
314890282Sobrien    }
314990282Sobrien  no_new_pseudos = 1;
315090282Sobrien
315190282Sobrien  timevar_pop (TV_MODE_SWITCH);
315290282Sobrien#endif
315390282Sobrien
315490282Sobrien  timevar_push (TV_SCHED);
315590282Sobrien
315690282Sobrien#ifdef INSN_SCHEDULING
315790282Sobrien
315818334Speter  /* Print function header into sched dump now
315918334Speter     because doing the sched analysis makes some of the dump.  */
316018334Speter  if (optimize > 0 && flag_schedule_insns)
316118334Speter    {
316290282Sobrien      open_dump_file (DFI_sched, decl);
316352558Sobrien
316418334Speter      /* Do control and data sched analysis,
316518334Speter	 and write some of the results to dump file.  */
316618334Speter
316790282Sobrien      schedule_insns (rtl_dump_file);
316852558Sobrien
316990282Sobrien      close_dump_file (DFI_sched, print_rtl_with_bb, insns);
317052558Sobrien
317190282Sobrien      /* Register lifetime information was updated as part of verifying
317290282Sobrien	 the schedule.  */
317390282Sobrien      register_life_up_to_date = 1;
317418334Speter    }
317590282Sobrien#endif
317690282Sobrien  timevar_pop (TV_SCHED);
317718334Speter
317890282Sobrien  ggc_collect ();
317990282Sobrien
318052558Sobrien  /* Determine if the current function is a leaf before running reload
318152558Sobrien     since this can impact optimizations done by the prologue and
318252558Sobrien     epilogue thus changing register elimination offsets.  */
318352558Sobrien  current_function_is_leaf = leaf_function_p ();
318452558Sobrien
318590282Sobrien  timevar_push (TV_LOCAL_ALLOC);
318690282Sobrien  open_dump_file (DFI_lreg, decl);
318718334Speter
318890282Sobrien  /* Allocate pseudo-regs that are used only within 1 basic block.
318990282Sobrien
319052558Sobrien     RUN_JUMP_AFTER_RELOAD records whether or not we need to rerun the
319152558Sobrien     jump optimizer after register allocation and reloading are finished.  */
319252558Sobrien
319390282Sobrien  if (! register_life_up_to_date)
319490282Sobrien    recompute_reg_usage (insns, ! optimize_size);
319518334Speter
319690282Sobrien  /* Allocate the reg_renumber array.  */
319790282Sobrien  allocate_reg_info (max_regno, FALSE, TRUE);
319818334Speter
319990282Sobrien  /* And the reg_equiv_memory_loc array.  */
320090282Sobrien  reg_equiv_memory_loc = (rtx *) xcalloc (max_regno, sizeof (rtx));
320190282Sobrien
320290282Sobrien  allocate_initial_values (reg_equiv_memory_loc);
320390282Sobrien
320490282Sobrien  regclass (insns, max_reg_num (), rtl_dump_file);
320590282Sobrien  rebuild_label_notes_after_reload = local_alloc ();
320690282Sobrien
320790282Sobrien  timevar_pop (TV_LOCAL_ALLOC);
320890282Sobrien
320990282Sobrien  if (dump_file[DFI_lreg].enabled)
321050615Sobrien    {
321190282Sobrien      timevar_push (TV_DUMP);
321252558Sobrien
321390282Sobrien      dump_flow_info (rtl_dump_file);
321490282Sobrien      dump_local_alloc (rtl_dump_file);
321552558Sobrien
321690282Sobrien      close_dump_file (DFI_lreg, print_rtl_with_bb, insns);
321790282Sobrien      timevar_pop (TV_DUMP);
321850615Sobrien    }
321918334Speter
322090282Sobrien  ggc_collect ();
322118334Speter
322290282Sobrien  timevar_push (TV_GLOBAL_ALLOC);
322390282Sobrien  open_dump_file (DFI_greg, decl);
322418334Speter
322590282Sobrien  /* If optimizing, allocate remaining pseudo-regs.  Do the reload
322690282Sobrien     pass fixing up any insns that are invalid.  */
322718334Speter
322890282Sobrien  if (optimize)
322990282Sobrien    failure = global_alloc (rtl_dump_file);
323090282Sobrien  else
323190282Sobrien    {
323290282Sobrien      build_insn_chain (insns);
323390282Sobrien      failure = reload (insns, 0);
323490282Sobrien    }
323518334Speter
323690282Sobrien  timevar_pop (TV_GLOBAL_ALLOC);
323790282Sobrien
323890282Sobrien  if (dump_file[DFI_greg].enabled)
323990282Sobrien    {
324090282Sobrien      timevar_push (TV_DUMP);
324190282Sobrien
324290282Sobrien      dump_global_regs (rtl_dump_file);
324390282Sobrien
324490282Sobrien      close_dump_file (DFI_greg, print_rtl_with_bb, insns);
324590282Sobrien      timevar_pop (TV_DUMP);
324690282Sobrien    }
324790282Sobrien
324818334Speter  if (failure)
324918334Speter    goto exit_rest_of_compilation;
325018334Speter
325190282Sobrien  ggc_collect ();
325290282Sobrien
325390282Sobrien  open_dump_file (DFI_postreload, decl);
325490282Sobrien
325550615Sobrien  /* Do a very simple CSE pass over just the hard registers.  */
325650615Sobrien  if (optimize > 0)
325790282Sobrien    {
325890282Sobrien      timevar_push (TV_RELOAD_CSE_REGS);
325990282Sobrien      reload_cse_regs (insns);
326090282Sobrien      timevar_pop (TV_RELOAD_CSE_REGS);
326190282Sobrien    }
326250615Sobrien
326352558Sobrien  /* Register allocation and reloading may have turned an indirect jump into
326452558Sobrien     a direct jump.  If so, we must rebuild the JUMP_LABEL fields of
326552558Sobrien     jumping instructions.  */
326652558Sobrien  if (rebuild_label_notes_after_reload)
326790282Sobrien    {
326890282Sobrien      timevar_push (TV_JUMP);
326952558Sobrien
327090282Sobrien      rebuild_jump_labels (insns);
327152558Sobrien
327290282Sobrien      timevar_pop (TV_JUMP);
327390282Sobrien    }
327452558Sobrien
327590282Sobrien  close_dump_file (DFI_postreload, print_rtl_with_bb, insns);
327652558Sobrien
327790282Sobrien  /* Re-create the death notes which were deleted during reload.  */
327890282Sobrien  timevar_push (TV_FLOW2);
327990282Sobrien  open_dump_file (DFI_flow2, decl);
328052558Sobrien
328190282Sobrien#ifdef ENABLE_CHECKING
328290282Sobrien  verify_flow_info ();
328390282Sobrien#endif
328452558Sobrien
328590282Sobrien  /* If optimizing, then go ahead and split insns now.  */
328690282Sobrien  if (optimize > 0)
328790282Sobrien    split_all_insns (0);
328852558Sobrien
328990282Sobrien  cleanup_cfg (optimize ? CLEANUP_EXPENSIVE : 0);
329052558Sobrien
329190282Sobrien  /* On some machines, the prologue and epilogue code, or parts thereof,
329290282Sobrien     can be represented as RTL.  Doing so lets us schedule insns between
329390282Sobrien     it and the rest of the code and also allows delayed branch
329490282Sobrien     scheduling to operate in the epilogue.  */
329590282Sobrien  thread_prologue_and_epilogue_insns (insns);
329690282Sobrien
329796289Sobrien  /* Cross-jumping is O(N^3) on the number of edges, thus trying to
329896289Sobrien     perform cross-jumping on flow graphs which have a high connectivity
329996289Sobrien     will take a long time.  This is similar to the test to disable GCSE.  */
330096289Sobrien  cleanup_crossjump = CLEANUP_CROSSJUMP;
330196289Sobrien  if (n_basic_blocks > 1000 && n_edges / n_basic_blocks >= 20)
330296289Sobrien    {
330396289Sobrien      if (optimize && warn_disabled_optimization)
330496289Sobrien	warning ("crossjump disabled: %d > 1000 basic blocks and %d >= 20 edges/basic block",
330596289Sobrien                 n_basic_blocks, n_edges / n_basic_blocks);
330696289Sobrien      cleanup_crossjump = 0;
330796289Sobrien    }
330896289Sobrien
330952558Sobrien  if (optimize)
331052558Sobrien    {
331196289Sobrien      cleanup_cfg (CLEANUP_EXPENSIVE | cleanup_crossjump);
331290282Sobrien      life_analysis (insns, rtl_dump_file, PROP_FINAL);
331390282Sobrien
331490282Sobrien      /* This is kind of a heuristic.  We need to run combine_stack_adjustments
331590282Sobrien         even for machines with possibly nonzero RETURN_POPS_ARGS
331690282Sobrien         and ACCUMULATE_OUTGOING_ARGS.  We expect that only ports having
331790282Sobrien         push instructions will have popping returns.  */
331890282Sobrien#ifndef PUSH_ROUNDING
331990282Sobrien      if (!ACCUMULATE_OUTGOING_ARGS)
332090282Sobrien#endif
332190282Sobrien	combine_stack_adjustments ();
332290282Sobrien
332390282Sobrien      ggc_collect ();
332452558Sobrien    }
332552558Sobrien
332652558Sobrien  flow2_completed = 1;
332752558Sobrien
332890282Sobrien  close_dump_file (DFI_flow2, print_rtl_with_bb, insns);
332990282Sobrien  timevar_pop (TV_FLOW2);
333018334Speter
333190282Sobrien#ifdef HAVE_peephole2
333290282Sobrien  if (optimize > 0 && flag_peephole2)
333390282Sobrien    {
333490282Sobrien      timevar_push (TV_PEEPHOLE2);
333590282Sobrien      open_dump_file (DFI_peephole2, decl);
333618334Speter
333790282Sobrien      peephole2_optimize (rtl_dump_file);
333890282Sobrien
333990282Sobrien      close_dump_file (DFI_peephole2, print_rtl_with_bb, insns);
334090282Sobrien      timevar_pop (TV_PEEPHOLE2);
334190282Sobrien    }
334290282Sobrien#endif
334390282Sobrien
334496289Sobrien  if (optimize > 0 && (flag_rename_registers || flag_cprop_registers))
334550615Sobrien    {
334690282Sobrien      timevar_push (TV_RENAME_REGISTERS);
334790282Sobrien      open_dump_file (DFI_rnreg, decl);
334890282Sobrien
334990282Sobrien      if (flag_rename_registers)
335090282Sobrien        regrename_optimize ();
335190282Sobrien      if (flag_cprop_registers)
335290282Sobrien        copyprop_hardreg_forward ();
335390282Sobrien
335490282Sobrien      close_dump_file (DFI_rnreg, print_rtl_with_bb, insns);
335590282Sobrien      timevar_pop (TV_RENAME_REGISTERS);
335650615Sobrien    }
335752558Sobrien
335890282Sobrien  if (optimize > 0)
335990282Sobrien    {
336090282Sobrien      timevar_push (TV_IFCVT2);
336190282Sobrien      open_dump_file (DFI_ce2, decl);
336290282Sobrien
336390282Sobrien      if_convert (1);
336490282Sobrien
336590282Sobrien      close_dump_file (DFI_ce2, print_rtl_with_bb, insns);
336690282Sobrien      timevar_pop (TV_IFCVT2);
336790282Sobrien    }
336890282Sobrien#ifdef STACK_REGS
336990282Sobrien  if (optimize)
337090282Sobrien    split_all_insns (1);
337190282Sobrien#endif
337290282Sobrien
337390282Sobrien#ifdef INSN_SCHEDULING
337418334Speter  if (optimize > 0 && flag_schedule_insns_after_reload)
337518334Speter    {
337690282Sobrien      timevar_push (TV_SCHED2);
337790282Sobrien      open_dump_file (DFI_sched2, decl);
337818334Speter
337918334Speter      /* Do control and data sched analysis again,
338018334Speter	 and write some more of the results to dump file.  */
338118334Speter
338290282Sobrien      split_all_insns (1);
338318334Speter
338490282Sobrien      schedule_insns (rtl_dump_file);
338518334Speter
338690282Sobrien      close_dump_file (DFI_sched2, print_rtl_with_bb, insns);
338790282Sobrien      timevar_pop (TV_SCHED2);
338890282Sobrien
338990282Sobrien      ggc_collect ();
339018334Speter    }
339190282Sobrien#endif
339218334Speter
339318334Speter#ifdef LEAF_REGISTERS
339452558Sobrien  current_function_uses_only_leaf_regs
339552558Sobrien    = optimize > 0 && only_leaf_regs_used () && leaf_function_p ();
339618334Speter#endif
339718334Speter
339890282Sobrien#ifdef STACK_REGS
339990282Sobrien  timevar_push (TV_REG_STACK);
340090282Sobrien  open_dump_file (DFI_stack, decl);
340118334Speter
340290282Sobrien  reg_to_stack (insns, rtl_dump_file);
340390282Sobrien
340490282Sobrien  close_dump_file (DFI_stack, print_rtl_with_bb, insns);
340590282Sobrien  timevar_pop (TV_REG_STACK);
340690282Sobrien
340790282Sobrien  ggc_collect ();
340890282Sobrien#endif
340918334Speter  if (optimize > 0)
341018334Speter    {
341190282Sobrien      timevar_push (TV_REORDER_BLOCKS);
341290282Sobrien      open_dump_file (DFI_bbro, decl);
341352558Sobrien
341496289Sobrien      /* Last attempt to optimize CFG, as life analysis possibly removed
341596289Sobrien	 some instructions.  Note that we can't rerun crossjump at this
341696289Sobrien	 point, because it can turn a switch into a direct branch, which
341796289Sobrien	 can leave the tablejump address calculation in the code, which
341896289Sobrien	 can lead to referencing an undefined label.  */
341996289Sobrien      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
342090282Sobrien      if (flag_reorder_blocks)
342152558Sobrien	{
342290282Sobrien	  reorder_basic_blocks ();
342390282Sobrien	  cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
342452558Sobrien	}
342590282Sobrien
342690282Sobrien      close_dump_file (DFI_bbro, print_rtl_with_bb, insns);
342790282Sobrien      timevar_pop (TV_REORDER_BLOCKS);
342818334Speter    }
342990282Sobrien  compute_alignments ();
343018334Speter
343190282Sobrien  /* CFG is no longer maintained up-to-date.  */
343290282Sobrien  free_bb_for_insn ();
343390282Sobrien
343418334Speter  /* If a machine dependent reorganization is needed, call it.  */
343518334Speter#ifdef MACHINE_DEPENDENT_REORG
343690282Sobrien  timevar_push (TV_MACH_DEP);
343790282Sobrien  open_dump_file (DFI_mach, decl);
343850615Sobrien
343990282Sobrien  MACHINE_DEPENDENT_REORG (insns);
344090282Sobrien
344190282Sobrien  close_dump_file (DFI_mach, print_rtl, insns);
344290282Sobrien  timevar_pop (TV_MACH_DEP);
344390282Sobrien
344490282Sobrien  ggc_collect ();
344518334Speter#endif
344618334Speter
344790282Sobrien  purge_line_number_notes (insns);
344890282Sobrien  cleanup_barriers ();
344990282Sobrien
345018334Speter  /* If a scheduling pass for delayed branches is to be done,
345150615Sobrien     call the scheduling code.  */
345218334Speter
345318334Speter#ifdef DELAY_SLOTS
345418334Speter  if (optimize > 0 && flag_delayed_branch)
345518334Speter    {
345690282Sobrien      timevar_push (TV_DBR_SCHED);
345790282Sobrien      open_dump_file (DFI_dbr, decl);
345852558Sobrien
345990282Sobrien      dbr_schedule (insns, rtl_dump_file);
346052558Sobrien
346190282Sobrien      close_dump_file (DFI_dbr, print_rtl, insns);
346290282Sobrien      timevar_pop (TV_DBR_SCHED);
346390282Sobrien
346490282Sobrien      ggc_collect ();
346518334Speter    }
346618334Speter#endif
346718334Speter
346890282Sobrien#if defined (HAVE_ATTR_length) && !defined (STACK_REGS)
346990282Sobrien  timevar_push (TV_SHORTEN_BRANCH);
347090282Sobrien  split_all_insns_noflow ();
347190282Sobrien  timevar_pop (TV_SHORTEN_BRANCH);
347290282Sobrien#endif
347390282Sobrien
347490282Sobrien  convert_to_eh_region_ranges ();
347590282Sobrien
347618334Speter  /* Shorten branches.  */
347790282Sobrien  timevar_push (TV_SHORTEN_BRANCH);
347890282Sobrien  shorten_branches (get_insns ());
347990282Sobrien  timevar_pop (TV_SHORTEN_BRANCH);
348018334Speter
348190282Sobrien  current_function_nothrow = nothrow_function_p ();
348290282Sobrien  if (current_function_nothrow)
348390282Sobrien    /* Now we know that this can't throw; set the flag for the benefit
348490282Sobrien       of other functions later in this translation unit.  */
348590282Sobrien    TREE_NOTHROW (current_function_decl) = 1;
348652558Sobrien
348790282Sobrien  /* Now turn the rtl into assembler code.  */
348850615Sobrien
348990282Sobrien  timevar_push (TV_FINAL);
349090282Sobrien  {
349190282Sobrien    rtx x;
349290282Sobrien    const char *fnname;
349390282Sobrien
349490282Sobrien    /* Get the function's name, as described by its RTL.  This may be
349590282Sobrien       different from the DECL_NAME name used in the source file.  */
349690282Sobrien
349790282Sobrien    x = DECL_RTL (decl);
349890282Sobrien    if (GET_CODE (x) != MEM)
349990282Sobrien      abort ();
350090282Sobrien    x = XEXP (x, 0);
350190282Sobrien    if (GET_CODE (x) != SYMBOL_REF)
350290282Sobrien      abort ();
350390282Sobrien    fnname = XSTR (x, 0);
350490282Sobrien
350590282Sobrien    assemble_start_function (decl, fnname);
350690282Sobrien    final_start_function (insns, asm_out_file, optimize);
350790282Sobrien    final (insns, asm_out_file, optimize, 0);
350890282Sobrien    final_end_function ();
350990282Sobrien
351090282Sobrien#ifdef IA64_UNWIND_INFO
351190282Sobrien    /* ??? The IA-64 ".handlerdata" directive must be issued before
351290282Sobrien       the ".endp" directive that closes the procedure descriptor.  */
351390282Sobrien    output_function_exception_table ();
351418334Speter#endif
351518334Speter
351690282Sobrien    assemble_end_function (decl, fnname);
351718334Speter
351890282Sobrien#ifndef IA64_UNWIND_INFO
351990282Sobrien    /* Otherwise, it feels unclean to switch sections in the middle.  */
352090282Sobrien    output_function_exception_table ();
352190282Sobrien#endif
352218334Speter
352390282Sobrien    if (! quiet_flag)
352490282Sobrien      fflush (asm_out_file);
352518334Speter
352690282Sobrien    /* Release all memory allocated by flow.  */
352790282Sobrien    free_basic_block_vars (0);
352818334Speter
352990282Sobrien    /* Release all memory held by regsets now.  */
353090282Sobrien    regset_release_memory ();
353190282Sobrien  }
353290282Sobrien  timevar_pop (TV_FINAL);
353350615Sobrien
353490282Sobrien  ggc_collect ();
353552558Sobrien
353690282Sobrien  /* Write DBX symbols if requested.  */
353718334Speter
353818334Speter  /* Note that for those inline functions where we don't initially
353918334Speter     know for certain that we will be generating an out-of-line copy,
354018334Speter     the first invocation of this routine (rest_of_compilation) will
354118334Speter     skip over this code by doing a `goto exit_rest_of_compilation;'.
354218334Speter     Later on, finish_compilation will call rest_of_compilation again
354318334Speter     for those inline functions that need to have out-of-line copies
354418334Speter     generated.  During that call, we *will* be routed past here.  */
354518334Speter
354690282Sobrien  timevar_push (TV_SYMOUT);
354790282Sobrien  (*debug_hooks->function_decl) (decl);
354890282Sobrien  timevar_pop (TV_SYMOUT);
354918334Speter
355018334Speter exit_rest_of_compilation:
355118334Speter
355218334Speter  /* In case the function was not output,
355318334Speter     don't leave any temporary anonymous types
355418334Speter     queued up for sdb output.  */
355518334Speter#ifdef SDB_DEBUGGING_INFO
355618334Speter  if (write_symbols == SDB_DEBUG)
355718334Speter    sdbout_types (NULL_TREE);
355818334Speter#endif
355918334Speter
356018334Speter  reload_completed = 0;
356152558Sobrien  flow2_completed = 0;
356252558Sobrien  no_new_pseudos = 0;
356318334Speter
356490282Sobrien  timevar_push (TV_FINAL);
356518334Speter
356690282Sobrien  /* Clear out the insn_length contents now that they are no
356790282Sobrien     longer valid.  */
356890282Sobrien  init_insn_lengths ();
356918334Speter
357090282Sobrien  /* Clear out the real_constant_chain before some of the rtx's
357190282Sobrien     it runs through become garbage.  */
357290282Sobrien  clear_const_double_mem ();
357318334Speter
357490282Sobrien  /* Show no temporary slots allocated.  */
357590282Sobrien  init_temp_slots ();
357618334Speter
357790282Sobrien  free_basic_block_vars (0);
357890282Sobrien  free_bb_for_insn ();
357990282Sobrien
358090282Sobrien  timevar_pop (TV_FINAL);
358190282Sobrien
358250615Sobrien  /* Make sure volatile mem refs aren't considered valid operands for
358350615Sobrien     arithmetic insns.  We must call this here if this is a nested inline
358450615Sobrien     function, since the above code leaves us in the init_recog state
358550615Sobrien     (from final.c), and the function context push/pop code does not
358650615Sobrien     save/restore volatile_ok.
358718334Speter
358850615Sobrien     ??? Maybe it isn't necessary for expand_start_function to call this
358950615Sobrien     anymore if we do it here?  */
359050615Sobrien
359150615Sobrien  init_recog_no_volatile ();
359250615Sobrien
359390282Sobrien  /* We're done with this function.  Free up memory if we can.  */
359490282Sobrien  free_after_parsing (cfun);
359590282Sobrien  if (! DECL_DEFER_OUTPUT (decl))
359690282Sobrien    {
359790282Sobrien      free_after_compilation (cfun);
359818334Speter
359990282Sobrien      /* Clear integrate.c's pointer to the cfun structure we just
360090282Sobrien	 destroyed.  */
360190282Sobrien      DECL_SAVED_INSNS (decl) = 0;
360290282Sobrien    }
360390282Sobrien  cfun = 0;
360452558Sobrien
360590282Sobrien  ggc_collect ();
360690282Sobrien
360790282Sobrien  timevar_pop (TV_REST_OF_COMPILATION);
360818334Speter}
360918334Speter
361050615Sobrienstatic void
361150615Sobriendisplay_help ()
361250615Sobrien{
361390282Sobrien  int undoc;
361490282Sobrien  unsigned long i;
361590282Sobrien  const char *lang;
361650615Sobrien
361790282Sobrien  printf (_("  -ffixed-<register>      Mark <register> as being unavailable to the compiler\n"));
361890282Sobrien  printf (_("  -fcall-used-<register>  Mark <register> as being corrupted by function calls\n"));
361990282Sobrien  printf (_("  -fcall-saved-<register> Mark <register> as being preserved across functions\n"));
362090282Sobrien  printf (_("  -finline-limit=<number> Limits the size of inlined functions to <number>\n"));
362190282Sobrien  printf (_("  -fmessage-length=<number> Limits diagnostics messages lengths to <number> characters per line.  0 suppresses line-wrapping\n"));
362290282Sobrien  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"));
362390282Sobrien
362490282Sobrien  for (i = ARRAY_SIZE (f_options); i--;)
362550615Sobrien    {
362690282Sobrien      const char *description = f_options[i].description;
362790282Sobrien
362850615Sobrien      if (description != NULL && * description != 0)
362950615Sobrien	printf ("  -f%-21s %s\n",
363090282Sobrien		f_options[i].string, _(description));
363150615Sobrien    }
363290282Sobrien
363390282Sobrien  printf (_("  -O[number]              Set optimization level to [number]\n"));
363490282Sobrien  printf (_("  -Os                     Optimize for space rather than speed\n"));
363590282Sobrien  for (i = LAST_PARAM; i--;)
363650615Sobrien    {
363790282Sobrien      const char *description = compiler_params[i].help;
363890282Sobrien      const int length = 21-strlen(compiler_params[i].option);
363990282Sobrien
364050615Sobrien      if (description != NULL && * description != 0)
364190282Sobrien	printf ("  --param %s=<value>%.*s%s\n",
364290282Sobrien		compiler_params[i].option,
364390282Sobrien		length > 0 ? length : 1, "                     ",
364490282Sobrien		_(description));
364590282Sobrien    }
364690282Sobrien  printf (_("  -pedantic               Issue warnings needed by strict compliance to ISO C\n"));
364790282Sobrien  printf (_("  -pedantic-errors        Like -pedantic except that errors are produced\n"));
364890282Sobrien  printf (_("  -w                      Suppress warnings\n"));
364990282Sobrien  printf (_("  -W                      Enable extra warnings\n"));
365090282Sobrien
365190282Sobrien  for (i = ARRAY_SIZE (W_options); i--;)
365290282Sobrien    {
365390282Sobrien      const char *description = W_options[i].description;
365490282Sobrien
365590282Sobrien      if (description != NULL && * description != 0)
365650615Sobrien	printf ("  -W%-21s %s\n",
365790282Sobrien		W_options[i].string, _(description));
365850615Sobrien    }
365990282Sobrien
366090282Sobrien  printf (_("  -Wunused                Enable unused warnings\n"));
366190282Sobrien  printf (_("  -Wlarger-than-<number>  Warn if an object is larger than <number> bytes\n"));
366290282Sobrien  printf (_("  -p                      Enable function profiling\n"));
366390282Sobrien  printf (_("  -o <file>               Place output into <file> \n"));
366490282Sobrien  printf (_("\
366590282Sobrien  -G <number>             Put global and static data smaller than <number>\n\
366690282Sobrien                          bytes into a special section (on some targets)\n"));
366790282Sobrien
366890282Sobrien  for (i = ARRAY_SIZE (debug_args); i--;)
366950615Sobrien    {
367050615Sobrien      if (debug_args[i].description != NULL)
367190282Sobrien	printf ("  -g%-21s %s\n",
367290282Sobrien		debug_args[i].arg, _(debug_args[i].description));
367350615Sobrien    }
367490282Sobrien
367590282Sobrien  printf (_("  -aux-info <file>        Emit declaration info into <file>\n"));
367690282Sobrien  printf (_("  -quiet                  Do not display functions compiled or elapsed time\n"));
367790282Sobrien  printf (_("  -version                Display the compiler's version\n"));
367890282Sobrien  printf (_("  -d[letters]             Enable dumps from specific passes of the compiler\n"));
367990282Sobrien  printf (_("  -dumpbase <file>        Base name to be used for dumps from specific passes\n"));
368090282Sobrien#if defined INSN_SCHEDULING
368190282Sobrien  printf (_("  -fsched-verbose=<number> Set the verbosity level of the scheduler\n"));
368250615Sobrien#endif
368390282Sobrien  printf (_("  --help                  Display this information\n"));
368450615Sobrien
368550615Sobrien  undoc = 0;
368650615Sobrien  lang  = "language";
368790282Sobrien
368850615Sobrien  /* Display descriptions of language specific options.
368950615Sobrien     If there is no description, note that there is an undocumented option.
369050615Sobrien     If the description is empty, do not display anything.  (This allows
369150615Sobrien     options to be deliberately undocumented, for whatever reason).
369250615Sobrien     If the option string is missing, then this is a marker, indicating
369352558Sobrien     that the description string is in fact the name of a language, whose
369450615Sobrien     language specific options are to follow.  */
369590282Sobrien
369690282Sobrien  if (ARRAY_SIZE (documented_lang_options) > 1)
369750615Sobrien    {
369890282Sobrien      printf (_("\nLanguage specific options:\n"));
369950615Sobrien
370090282Sobrien      for (i = 0; i < ARRAY_SIZE (documented_lang_options); i++)
370150615Sobrien	{
370290282Sobrien	  const char *description = documented_lang_options[i].description;
370390282Sobrien	  const char *option      = documented_lang_options[i].option;
370450615Sobrien
370550615Sobrien	  if (description == NULL)
370652558Sobrien	    {
370752558Sobrien	      undoc = 1;
370852558Sobrien
370952558Sobrien	      if (extra_warnings)
371090282Sobrien		printf (_("  %-23.23s [undocumented]\n"), option);
371152558Sobrien	    }
371290282Sobrien	  else if (*description == 0)
371350615Sobrien	    continue;
371450615Sobrien	  else if (option == NULL)
371550615Sobrien	    {
371650615Sobrien	      if (undoc)
371750615Sobrien		printf
371890282Sobrien		  (_("\nThere are undocumented %s specific options as well.\n"),
371950615Sobrien			lang);
372050615Sobrien	      undoc = 0;
372150615Sobrien
372290282Sobrien	      printf (_("\n Options for %s:\n"), description);
372390282Sobrien
372450615Sobrien	      lang = description;
372550615Sobrien	    }
372650615Sobrien	  else
372790282Sobrien	    printf ("  %-23.23s %s\n", option, _(description));
372850615Sobrien	}
372950615Sobrien    }
373050615Sobrien
373150615Sobrien  if (undoc)
373290282Sobrien    printf (_("\nThere are undocumented %s specific options as well.\n"),
373390282Sobrien	    lang);
373450615Sobrien
373590282Sobrien  display_target_options ();
373690282Sobrien}
373790282Sobrien
373890282Sobrienstatic void
373990282Sobriendisplay_target_options ()
374090282Sobrien{
374190282Sobrien  int undoc, i;
374290282Sobrien  static bool displayed = false;
374390282Sobrien
374490282Sobrien  /* Avoid double printing for --help --target-help.  */
374590282Sobrien  if (displayed)
374690282Sobrien    return;
374790282Sobrien  displayed = true;
374890282Sobrien
374990282Sobrien  if (ARRAY_SIZE (target_switches) > 1
375050615Sobrien#ifdef TARGET_OPTIONS
375190282Sobrien      || ARRAY_SIZE (target_options) > 1
375250615Sobrien#endif
375350615Sobrien      )
375450615Sobrien    {
375550615Sobrien      int doc = 0;
375690282Sobrien
375750615Sobrien      undoc = 0;
375850615Sobrien
375990282Sobrien      printf (_("\nTarget specific options:\n"));
376090282Sobrien
376190282Sobrien      for (i = ARRAY_SIZE (target_switches); i--;)
376250615Sobrien	{
376390282Sobrien	  const char *option      = target_switches[i].name;
376490282Sobrien	  const char *description = target_switches[i].description;
376550615Sobrien
376690282Sobrien	  if (option == NULL || *option == 0)
376750615Sobrien	    continue;
376850615Sobrien	  else if (description == NULL)
376952558Sobrien	    {
377052558Sobrien	      undoc = 1;
377190282Sobrien
377252558Sobrien	      if (extra_warnings)
377390282Sobrien		printf (_("  -m%-23.23s [undocumented]\n"), option);
377452558Sobrien	    }
377550615Sobrien	  else if (* description != 0)
377690282Sobrien	    doc += printf ("  -m%-23.23s %s\n", option, _(description));
377750615Sobrien	}
377890282Sobrien
377990282Sobrien#ifdef TARGET_OPTIONS
378090282Sobrien      for (i = ARRAY_SIZE (target_options); i--;)
378150615Sobrien	{
378290282Sobrien	  const char *option      = target_options[i].prefix;
378390282Sobrien	  const char *description = target_options[i].description;
378450615Sobrien
378590282Sobrien	  if (option == NULL || *option == 0)
378650615Sobrien	    continue;
378750615Sobrien	  else if (description == NULL)
378852558Sobrien	    {
378952558Sobrien	      undoc = 1;
379090282Sobrien
379152558Sobrien	      if (extra_warnings)
379290282Sobrien		printf (_("  -m%-23.23s [undocumented]\n"), option);
379352558Sobrien	    }
379450615Sobrien	  else if (* description != 0)
379590282Sobrien	    doc += printf ("  -m%-23.23s %s\n", option, _(description));
379650615Sobrien	}
379750615Sobrien#endif
379850615Sobrien      if (undoc)
379952558Sobrien	{
380052558Sobrien	  if (doc)
380190282Sobrien	    printf (_("\nThere are undocumented target specific options as well.\n"));
380252558Sobrien	  else
380390282Sobrien	    printf (_("  They exist, but they are not documented.\n"));
380452558Sobrien	}
380550615Sobrien    }
380650615Sobrien}
380790282Sobrien
380890282Sobrien/* Parse a -d... command line switch.  */
380950615Sobrien
381090282Sobrienstatic void
381190282Sobriendecode_d_option (arg)
381290282Sobrien     const char *arg;
381390282Sobrien{
381490282Sobrien  int i, c, matched;
381550615Sobrien
381690282Sobrien  while (*arg)
381790282Sobrien    switch (c = *arg++)
381890282Sobrien      {
381990282Sobrien      case 'a':
382090282Sobrien	for (i = 0; i < (int) DFI_MAX; ++i)
382190282Sobrien	  dump_file[i].enabled = 1;
382290282Sobrien	break;
382390282Sobrien      case 'A':
382490282Sobrien	flag_debug_asm = 1;
382590282Sobrien	break;
382690282Sobrien      case 'p':
382790282Sobrien	flag_print_asm_name = 1;
382890282Sobrien	break;
382990282Sobrien      case 'P':
383090282Sobrien        flag_dump_rtl_in_asm = 1;
383190282Sobrien        flag_print_asm_name = 1;
383290282Sobrien        break;
383390282Sobrien      case 'v':
383490282Sobrien	graph_dump_format = vcg;
383590282Sobrien	break;
383690282Sobrien      case 'x':
383790282Sobrien	rtl_dump_and_exit = 1;
383890282Sobrien	break;
383990282Sobrien      case 'y':
384090282Sobrien	(*lang_hooks.set_yydebug) (1);
384190282Sobrien	break;
384290282Sobrien      case 'D':	/* These are handled by the preprocessor.  */
384390282Sobrien      case 'I':
384490282Sobrien	break;
384590282Sobrien
384690282Sobrien      default:
384790282Sobrien	matched = 0;
384890282Sobrien	for (i = 0; i < (int) DFI_MAX; ++i)
384990282Sobrien	  if (c == dump_file[i].debug_switch)
385090282Sobrien	    {
385190282Sobrien	      dump_file[i].enabled = 1;
385290282Sobrien	      matched = 1;
385390282Sobrien	    }
385490282Sobrien
385590282Sobrien	if (! matched)
385690282Sobrien	  warning ("unrecognized gcc debugging option: %c", c);
385790282Sobrien	break;
385890282Sobrien      }
385990282Sobrien}
386090282Sobrien
386190282Sobrien/* Parse a -f... command line switch.  ARG is the value after the -f.
386290282Sobrien   It is safe to access 'ARG - 2' to generate the full switch name.
386390282Sobrien   Return the number of strings consumed.  */
386490282Sobrien
386550615Sobrienstatic int
386690282Sobriendecode_f_option (arg)
386790282Sobrien     const char *arg;
386850615Sobrien{
386990282Sobrien  int j;
387090282Sobrien  const char *option_value = NULL;
387150615Sobrien
387290282Sobrien  /* Search for the option in the table of binary f options.  */
387390282Sobrien  for (j = ARRAY_SIZE (f_options); j--;)
387450615Sobrien    {
387590282Sobrien      if (!strcmp (arg, f_options[j].string))
387650615Sobrien	{
387790282Sobrien	  *f_options[j].variable = f_options[j].on_value;
387890282Sobrien	  return 1;
387950615Sobrien	}
388090282Sobrien
388190282Sobrien      if (arg[0] == 'n' && arg[1] == 'o' && arg[2] == '-'
388290282Sobrien	  && ! strcmp (arg + 3, f_options[j].string))
388390282Sobrien	{
388490282Sobrien	  *f_options[j].variable = ! f_options[j].on_value;
388590282Sobrien	  return 1;
388690282Sobrien	}
388750615Sobrien    }
388818334Speter
388990282Sobrien  if (!strcmp (arg, "fast-math"))
389090282Sobrien    set_fast_math_flags ();
389190282Sobrien  else if (!strcmp (arg, "no-fast-math"))
389290282Sobrien    set_no_fast_math_flags ();
389390282Sobrien  else if ((option_value = skip_leading_substring (arg, "inline-limit-"))
389490282Sobrien	   || (option_value = skip_leading_substring (arg, "inline-limit=")))
389590282Sobrien    {
389690282Sobrien      int val =
389790282Sobrien	read_integral_parameter (option_value, arg - 2,
389890282Sobrien				 MAX_INLINE_INSNS);
389990282Sobrien      set_param_value ("max-inline-insns", val);
390090282Sobrien    }
390190282Sobrien#ifdef INSN_SCHEDULING
390290282Sobrien  else if ((option_value = skip_leading_substring (arg, "sched-verbose=")))
390390282Sobrien    fix_sched_param ("verbose", option_value);
390418334Speter#endif
390590282Sobrien  else if ((option_value = skip_leading_substring (arg, "fixed-")))
390690282Sobrien    fix_register (option_value, 1, 1);
390790282Sobrien  else if ((option_value = skip_leading_substring (arg, "call-used-")))
390890282Sobrien    fix_register (option_value, 0, 1);
390990282Sobrien  else if ((option_value = skip_leading_substring (arg, "call-saved-")))
391090282Sobrien    fix_register (option_value, 0, 0);
391190282Sobrien  else if ((option_value = skip_leading_substring (arg, "align-loops=")))
391290282Sobrien    align_loops = read_integral_parameter (option_value, arg - 2, align_loops);
391390282Sobrien  else if ((option_value = skip_leading_substring (arg, "align-functions=")))
391490282Sobrien    align_functions
391590282Sobrien      = read_integral_parameter (option_value, arg - 2, align_functions);
391690282Sobrien  else if ((option_value = skip_leading_substring (arg, "align-jumps=")))
391790282Sobrien    align_jumps = read_integral_parameter (option_value, arg - 2, align_jumps);
391890282Sobrien  else if ((option_value = skip_leading_substring (arg, "align-labels=")))
391990282Sobrien    align_labels
392090282Sobrien      = read_integral_parameter (option_value, arg - 2, align_labels);
392190282Sobrien  else if ((option_value
392290282Sobrien	    = skip_leading_substring (arg, "stack-limit-register=")))
392390282Sobrien    {
392490282Sobrien      int reg = decode_reg_name (option_value);
392590282Sobrien      if (reg < 0)
392690282Sobrien	error ("unrecognized register name `%s'", option_value);
392790282Sobrien      else
392890282Sobrien	stack_limit_rtx = gen_rtx_REG (Pmode, reg);
392990282Sobrien    }
393090282Sobrien  else if ((option_value
393190282Sobrien	    = skip_leading_substring (arg, "stack-limit-symbol=")))
393290282Sobrien    {
393390282Sobrien      const char *nm;
393490282Sobrien      nm = ggc_strdup (option_value);
393590282Sobrien      stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, nm);
393690282Sobrien    }
393790282Sobrien  else if ((option_value
393890282Sobrien            = skip_leading_substring (arg, "message-length=")))
393990282Sobrien    output_set_maximum_length
394090282Sobrien      (&global_dc->buffer, read_integral_parameter
394190282Sobrien       (option_value, arg - 2, diagnostic_line_cutoff (global_dc)));
394290282Sobrien  else if ((option_value
394390282Sobrien	    = skip_leading_substring (arg, "diagnostics-show-location=")))
394490282Sobrien    {
394590282Sobrien      if (!strcmp (option_value, "once"))
394690282Sobrien        diagnostic_prefixing_rule (global_dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
394790282Sobrien      else if (!strcmp (option_value, "every-line"))
394890282Sobrien        diagnostic_prefixing_rule (global_dc)
394990282Sobrien          = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
395090282Sobrien      else
395190282Sobrien	error ("unrecognized option `%s'", arg - 2);
395290282Sobrien    }
395390282Sobrien  else if (!strcmp (arg, "no-stack-limit"))
395490282Sobrien    stack_limit_rtx = NULL_RTX;
395590282Sobrien  else if (!strcmp (arg, "preprocessed"))
395690282Sobrien    /* Recognise this switch but do nothing.  This prevents warnings
395790282Sobrien       about an unrecognized switch if cpplib has not been linked in.  */
395890282Sobrien    ;
395990282Sobrien  else
396090282Sobrien    return 0;
396118334Speter
396290282Sobrien  return 1;
396390282Sobrien}
396418334Speter
396590282Sobrien/* Parse a -W... command line switch.  ARG is the value after the -W.
396690282Sobrien   It is safe to access 'ARG - 2' to generate the full switch name.
396790282Sobrien   Return the number of strings consumed.  */
396818334Speter
396990282Sobrienstatic int
397090282Sobriendecode_W_option (arg)
397190282Sobrien     const char *arg;
397290282Sobrien{
397390282Sobrien  const char *option_value = NULL;
397490282Sobrien  int j;
397552558Sobrien
397690282Sobrien  /* Search for the option in the table of binary W options.  */
397718334Speter
397890282Sobrien  for (j = ARRAY_SIZE (W_options); j--;)
397918334Speter    {
398090282Sobrien      if (!strcmp (arg, W_options[j].string))
398118334Speter	{
398290282Sobrien	  *W_options[j].variable = W_options[j].on_value;
398390282Sobrien	  return 1;
398418334Speter	}
398590282Sobrien
398690282Sobrien      if (arg[0] == 'n' && arg[1] == 'o' && arg[2] == '-'
398790282Sobrien	  && ! strcmp (arg + 3, W_options[j].string))
398818334Speter	{
398990282Sobrien	  *W_options[j].variable = ! W_options[j].on_value;
399090282Sobrien	  return 1;
399118334Speter	}
399218334Speter    }
399318334Speter
399490282Sobrien  if ((option_value = skip_leading_substring (arg, "id-clash-")))
399590282Sobrien    warning ("-Wid-clash-LEN is no longer supported");
399690282Sobrien  else if ((option_value = skip_leading_substring (arg, "larger-than-")))
399790282Sobrien    {
399890282Sobrien      larger_than_size = read_integral_parameter (option_value, arg - 2, -1);
399918334Speter
400090282Sobrien      warn_larger_than = larger_than_size != -1;
400118334Speter    }
400290282Sobrien  else if (!strcmp (arg, "unused"))
400318334Speter    {
400490282Sobrien      set_Wunused (1);
400518334Speter    }
400690282Sobrien  else if (!strcmp (arg, "no-unused"))
400718334Speter    {
400890282Sobrien      set_Wunused (0);
400918334Speter    }
401090282Sobrien  else
401190282Sobrien    return 0;
401218334Speter
401390282Sobrien  return 1;
401490282Sobrien}
401550615Sobrien
401690282Sobrien/* Parse a -g... command line switch.  ARG is the value after the -g.
401790282Sobrien   It is safe to access 'ARG - 2' to generate the full switch name.
401890282Sobrien   Return the number of strings consumed.  */
401918334Speter
402090282Sobrienstatic int
402190282Sobriendecode_g_option (arg)
402290282Sobrien     const char *arg;
402390282Sobrien{
402490282Sobrien  static unsigned level=0;
402590282Sobrien  /* A lot of code assumes write_symbols == NO_DEBUG if the
402690282Sobrien     debugging level is 0 (thus -gstabs1 -gstabs0 would lose track
402790282Sobrien     of what debugging type has been selected).  This records the
402890282Sobrien     selected type.  It is an error to specify more than one
402990282Sobrien     debugging type.  */
403090282Sobrien  static enum debug_info_type selected_debug_type = NO_DEBUG;
403190282Sobrien  /* Non-zero if debugging format has been explicitly set.
403290282Sobrien     -g and -ggdb don't explicitly set the debugging format so
403390282Sobrien     -gdwarf -g3 is equivalent to -gdwarf3.  */
403490282Sobrien  static int type_explicitly_set_p = 0;
403590282Sobrien  /* Indexed by enum debug_info_type.  */
403690282Sobrien  static const char *const debug_type_names[] =
403790282Sobrien  {
403890282Sobrien    "none", "stabs", "coff", "dwarf-1", "dwarf-2", "xcoff", "vms"
403990282Sobrien  };
404018334Speter
404190282Sobrien  /* The maximum admissible debug level value.  */
404290282Sobrien  static const unsigned max_debug_level = 3;
404390282Sobrien
404490282Sobrien  /* Look up ARG in the table.  */
404590282Sobrien  for (da = debug_args; da->arg; da++)
404618334Speter    {
404790282Sobrien      const int da_len = strlen (da->arg);
404890282Sobrien
404990282Sobrien      if (da_len == 0 || ! strncmp (arg, da->arg, da_len))
405050615Sobrien	{
405190282Sobrien	  enum debug_info_type type = da->debug_type;
405290282Sobrien	  const char *p = arg + da_len;
405318334Speter
405490282Sobrien	  if (*p && ! ISDIGIT (*p))
405590282Sobrien	    continue;
405618334Speter
405790282Sobrien	  /* A debug flag without a level defaults to level 2.
405890282Sobrien	     Note we do not want to call read_integral_parameter
405990282Sobrien	     for that case since it will call atoi which
406090282Sobrien	     will return zero.
406118334Speter
406290282Sobrien	     ??? We may want to generalize the interface to
406390282Sobrien	     read_integral_parameter to better handle this case
406490282Sobrien	     if this case shows up often.  */
406590282Sobrien	  if (*p)
406690282Sobrien	    level = read_integral_parameter (p, 0, max_debug_level + 1);
406790282Sobrien	  else
406890282Sobrien	    level = (level == 0) ? 2 : level;
406918334Speter
407090282Sobrien	  if (da_len > 1 && *p && !strncmp (arg, "dwarf", da_len))
407118334Speter	    {
407290282Sobrien	      error ("use -gdwarf -g%d for DWARF v1, level %d",
407390282Sobrien		     level, level);
407490282Sobrien	      if (level == 2)
407590282Sobrien		error ("use -gdwarf-2   for DWARF v2");
407618334Speter	    }
407790282Sobrien
407890282Sobrien	  if (level > max_debug_level)
407918334Speter	    {
408090282Sobrien	      warning ("\
408190282Sobrienignoring option `%s' due to invalid debug level specification",
408290282Sobrien		       arg - 2);
408390282Sobrien	      level = debug_info_level;
408418334Speter	    }
408518334Speter
408690282Sobrien	  if (type == NO_DEBUG)
408718334Speter	    {
408890282Sobrien	      type = PREFERRED_DEBUGGING_TYPE;
408918334Speter
409090282Sobrien	      if (da_len > 1 && strncmp (arg, "gdb", da_len) == 0)
409118334Speter		{
409296289Sobrien#ifdef DWARF2_DEBUGGING_INFO
409390282Sobrien		  type = DWARF2_DEBUG;
409450615Sobrien#else
409518334Speter#ifdef DBX_DEBUGGING_INFO
409690282Sobrien		  type = DBX_DEBUG;
409750615Sobrien#endif
409850615Sobrien#endif
409990282Sobrien		}
410090282Sobrien	    }
410118334Speter
410290282Sobrien	  if (type == NO_DEBUG)
410390282Sobrien	    warning ("`%s': unknown or unsupported -g option", arg - 2);
410418334Speter
410590282Sobrien	  /* Does it conflict with an already selected type?  */
410690282Sobrien	  if (type_explicitly_set_p
410790282Sobrien	      /* -g/-ggdb don't conflict with anything.  */
410890282Sobrien	      && da->debug_type != NO_DEBUG
410990282Sobrien	      && type != selected_debug_type)
411090282Sobrien	    warning ("`%s' ignored, conflicts with `-g%s'",
411190282Sobrien		     arg - 2, debug_type_names[(int) selected_debug_type]);
411290282Sobrien	  else
411318334Speter	    {
411490282Sobrien	      /* If the format has already been set, -g/-ggdb
411590282Sobrien		 only change the debug level.  */
411690282Sobrien	      if (type_explicitly_set_p && da->debug_type == NO_DEBUG)
411790282Sobrien		/* Don't change debugging type.  */
411890282Sobrien		;
411952558Sobrien	      else
412090282Sobrien		{
412190282Sobrien		  selected_debug_type = type;
412290282Sobrien		  type_explicitly_set_p = da->debug_type != NO_DEBUG;
412352558Sobrien		}
412490282Sobrien
412590282Sobrien	      write_symbols = (level == 0
412690282Sobrien			       ? NO_DEBUG
412790282Sobrien			       : selected_debug_type);
412890282Sobrien	      use_gnu_debug_info_extensions = da->use_extensions_p;
412990282Sobrien	      debug_info_level = (enum debug_info_level) level;
413018334Speter	    }
413190282Sobrien
413290282Sobrien	  break;
413318334Speter	}
413418334Speter    }
413518334Speter
413690282Sobrien  if (! da->arg)
413790282Sobrien    return 0;
413818334Speter
413990282Sobrien  return 1;
414090282Sobrien}
414190282Sobrien
414290282Sobrien/* Decode the first argument in the argv as a language-independent option.
414390282Sobrien   Return the number of strings consumed.  */
414490282Sobrien
414590282Sobrienstatic unsigned int
414690282Sobrienindependent_decode_option (argc, argv)
414790282Sobrien     int argc;
414890282Sobrien     char **argv;
414990282Sobrien{
415090282Sobrien  char *arg = argv[0];
415190282Sobrien
415290282Sobrien  if (arg[0] != '-' || arg[1] == 0)
415318334Speter    {
415490282Sobrien      if (arg[0] == '+')
415590282Sobrien	return 0;
415618334Speter
415790282Sobrien      filename = arg;
415890282Sobrien
415990282Sobrien      return 1;
416018334Speter    }
416118334Speter
416290282Sobrien  arg++;
416318334Speter
416490282Sobrien  if (!strcmp (arg, "-help"))
416550615Sobrien    {
416690282Sobrien      display_help ();
416790282Sobrien      exit_after_options = 1;
416850615Sobrien    }
416950615Sobrien
417090282Sobrien  if (!strcmp (arg, "-target-help"))
417150615Sobrien    {
417290282Sobrien      display_target_options ();
417390282Sobrien      exit_after_options = 1;
417450615Sobrien    }
417550615Sobrien
417690282Sobrien  if (!strcmp (arg, "-version"))
417718334Speter    {
417890282Sobrien      print_version (stderr, "");
417990282Sobrien      exit_after_options = 1;
418018334Speter    }
418118334Speter
418290282Sobrien  /* Handle '--param <name>=<value>'.  */
418390282Sobrien  if (strcmp (arg, "-param") == 0)
418490282Sobrien    {
418590282Sobrien      char *equal;
418618334Speter
418790282Sobrien      if (argc == 1)
418852558Sobrien	{
418990282Sobrien	  error ("-param option missing argument");
419090282Sobrien	  return 1;
419152558Sobrien	}
419290282Sobrien
419390282Sobrien      /* Get the '<name>=<value>' parameter.  */
419490282Sobrien      arg = argv[1];
419590282Sobrien      /* Look for the `='.  */
419690282Sobrien      equal = strchr (arg, '=');
419790282Sobrien      if (!equal)
419890282Sobrien	error ("invalid --param option: %s", arg);
419952558Sobrien      else
420090282Sobrien	{
420190282Sobrien	  int val;
420252558Sobrien
420390282Sobrien	  /* Zero out the `=' sign so that we get two separate strings.  */
420490282Sobrien	  *equal = '\0';
420590282Sobrien	  /* Figure out what value is specified.  */
420690282Sobrien	  val = read_integral_parameter (equal + 1, NULL, INVALID_PARAM_VAL);
420790282Sobrien	  if (val != INVALID_PARAM_VAL)
420890282Sobrien	    set_param_value (arg, val);
420990282Sobrien	  else
421090282Sobrien	    error ("invalid parameter value `%s'", equal + 1);
421190282Sobrien	}
421290282Sobrien
421390282Sobrien      return 2;
421418334Speter    }
421518334Speter
421690282Sobrien  if (*arg == 'Y')
421790282Sobrien    arg++;
421818334Speter
421990282Sobrien  switch (*arg)
422018334Speter    {
422190282Sobrien    default:
422290282Sobrien      return 0;
422318334Speter
422490282Sobrien    case 'O':
422590282Sobrien      /* Already been treated in main (). Do nothing.  */
422690282Sobrien      break;
422718334Speter
422890282Sobrien    case 'm':
422990282Sobrien      set_target_switch (arg + 1);
423090282Sobrien      break;
423190282Sobrien
423290282Sobrien    case 'f':
423390282Sobrien      return decode_f_option (arg + 1);
423490282Sobrien
423590282Sobrien    case 'g':
423690282Sobrien      return decode_g_option (arg + 1);
423790282Sobrien
423890282Sobrien    case 'd':
423990282Sobrien      if (!strcmp (arg, "dumpbase"))
424090282Sobrien	{
424190282Sobrien	  if (argc == 1)
424290282Sobrien	    return 0;
424390282Sobrien
424490282Sobrien	  dump_base_name = argv[1];
424590282Sobrien	  return 2;
424690282Sobrien	}
424790282Sobrien      else
424890282Sobrien	decode_d_option (arg + 1);
424990282Sobrien      break;
425090282Sobrien
425190282Sobrien    case 'p':
425290282Sobrien      if (!strcmp (arg, "pedantic"))
425390282Sobrien	pedantic = 1;
425490282Sobrien      else if (!strcmp (arg, "pedantic-errors"))
425590282Sobrien	flag_pedantic_errors = pedantic = 1;
425690282Sobrien      else if (arg[1] == 0)
425790282Sobrien	profile_flag = 1;
425890282Sobrien      else
425990282Sobrien	return 0;
426090282Sobrien      break;
426190282Sobrien
426290282Sobrien    case 'q':
426390282Sobrien      if (!strcmp (arg, "quiet"))
426490282Sobrien	quiet_flag = 1;
426590282Sobrien      else
426690282Sobrien	return 0;
426790282Sobrien      break;
426890282Sobrien
426990282Sobrien    case 'v':
427090282Sobrien      if (!strcmp (arg, "version"))
427190282Sobrien	version_flag = 1;
427290282Sobrien      else
427390282Sobrien	return 0;
427490282Sobrien      break;
427590282Sobrien
427690282Sobrien    case 'w':
427790282Sobrien      if (arg[1] == 0)
427890282Sobrien	inhibit_warnings = 1;
427990282Sobrien      else
428090282Sobrien	return 0;
428190282Sobrien      break;
428290282Sobrien
428390282Sobrien    case 'W':
428490282Sobrien      if (arg[1] == 0)
428590282Sobrien	{
428690282Sobrien	  extra_warnings = 1;
428790282Sobrien	  /* We save the value of warn_uninitialized, since if they put
428890282Sobrien	     -Wuninitialized on the command line, we need to generate a
428990282Sobrien	     warning about not using it without also specifying -O.  */
429090282Sobrien	  if (warn_uninitialized != 1)
429190282Sobrien	    warn_uninitialized = 2;
429290282Sobrien	}
429390282Sobrien      else
429490282Sobrien	return decode_W_option (arg + 1);
429590282Sobrien      break;
429690282Sobrien
429790282Sobrien    case 'a':
429890282Sobrien      if (!strncmp (arg, "aux-info", 8))
429990282Sobrien	{
430090282Sobrien	  if (arg[8] == '\0')
430190282Sobrien	    {
430290282Sobrien	      if (argc == 1)
430390282Sobrien		return 0;
430490282Sobrien
430590282Sobrien	      aux_info_file_name = argv[1];
430690282Sobrien	      flag_gen_aux_info = 1;
430790282Sobrien	      return 2;
430890282Sobrien	    }
430990282Sobrien	  else if (arg[8] == '=')
431090282Sobrien	    {
431190282Sobrien	      aux_info_file_name = arg + 9;
431290282Sobrien	      flag_gen_aux_info = 1;
431390282Sobrien	    }
431490282Sobrien	  else
431590282Sobrien	    return 0;
431690282Sobrien	}
431790282Sobrien      else
431890282Sobrien	return 0;
431990282Sobrien      break;
432090282Sobrien
432190282Sobrien    case 'o':
432290282Sobrien      if (arg[1] == 0)
432390282Sobrien	{
432490282Sobrien	  if (argc == 1)
432590282Sobrien	    return 0;
432690282Sobrien
432790282Sobrien	  asm_file_name = argv[1];
432890282Sobrien	  return 2;
432990282Sobrien	}
433090282Sobrien      return 0;
433190282Sobrien
433290282Sobrien    case 'G':
433390282Sobrien      {
433490282Sobrien	int g_switch_val;
433590282Sobrien	int return_val;
433690282Sobrien
433790282Sobrien	if (arg[1] == 0)
433890282Sobrien	  {
433990282Sobrien	    if (argc == 1)
434090282Sobrien	      return 0;
434190282Sobrien
434290282Sobrien	    g_switch_val = read_integral_parameter (argv[1], 0, -1);
434390282Sobrien	    return_val = 2;
434490282Sobrien	  }
434590282Sobrien	else
434690282Sobrien	  {
434790282Sobrien	    g_switch_val = read_integral_parameter (arg + 1, 0, -1);
434890282Sobrien	    return_val = 1;
434990282Sobrien	  }
435090282Sobrien
435190282Sobrien	if (g_switch_val == -1)
435290282Sobrien	  return_val = 0;
435390282Sobrien	else
435490282Sobrien	  {
435590282Sobrien	    g_switch_set = TRUE;
435690282Sobrien	    g_switch_value = g_switch_val;
435790282Sobrien	  }
435890282Sobrien
435990282Sobrien	return return_val;
436090282Sobrien      }
436118334Speter    }
436218334Speter
436390282Sobrien  return 1;
436418334Speter}
436518334Speter
436618334Speter/* Decode -m switches.  */
436718334Speter/* Decode the switch -mNAME.  */
436818334Speter
436952558Sobrienstatic void
437018334Speterset_target_switch (name)
437190282Sobrien     const char *name;
437218334Speter{
437390282Sobrien  size_t j;
437452558Sobrien  int valid_target_option = 0;
437518334Speter
437690282Sobrien  for (j = 0; j < ARRAY_SIZE (target_switches); j++)
437718334Speter    if (!strcmp (target_switches[j].name, name))
437818334Speter      {
437918334Speter	if (target_switches[j].value < 0)
438018334Speter	  target_flags &= ~-target_switches[j].value;
438118334Speter	else
438218334Speter	  target_flags |= target_switches[j].value;
438352558Sobrien	valid_target_option = 1;
438418334Speter      }
438518334Speter
438618334Speter#ifdef TARGET_OPTIONS
438752558Sobrien  if (!valid_target_option)
438890282Sobrien    for (j = 0; j < ARRAY_SIZE (target_options); j++)
438918334Speter      {
439018334Speter	int len = strlen (target_options[j].prefix);
439118334Speter	if (!strncmp (target_options[j].prefix, name, len))
439218334Speter	  {
439318334Speter	    *target_options[j].variable = name + len;
439452558Sobrien	    valid_target_option = 1;
439518334Speter	  }
439618334Speter      }
439718334Speter#endif
439818334Speter
439952558Sobrien  if (!valid_target_option)
440090282Sobrien    error ("invalid option `%s'", name);
440118334Speter}
440218334Speter
440350615Sobrien/* Print version information to FILE.
440450615Sobrien   Each line begins with INDENT (for the case where FILE is the
440550615Sobrien   assembler output file).  */
440618334Speter
440752558Sobrienstatic void
440850615Sobrienprint_version (file, indent)
440950615Sobrien     FILE *file;
441052558Sobrien     const char *indent;
441150615Sobrien{
441250615Sobrien#ifndef __VERSION__
441352558Sobrien#define __VERSION__ "[?]"
441450615Sobrien#endif
441552558Sobrien  fnotice (file,
441652558Sobrien#ifdef __GNUC__
441790282Sobrien	   "%s%s%s version %s (%s)\n%s\tcompiled by GNU C version %s.\n"
441850615Sobrien#else
441952558Sobrien	   "%s%s%s version %s (%s) compiled by CC.\n"
442050615Sobrien#endif
442152558Sobrien	   , indent, *indent != 0 ? " " : "",
442290282Sobrien	   lang_hooks.name, version_string, TARGET_NAME,
442390282Sobrien	   indent, __VERSION__);
442450615Sobrien}
442518334Speter
442650615Sobrien/* Print an option value and return the adjusted position in the line.
442750615Sobrien   ??? We don't handle error returns from fprintf (disk full); presumably
442850615Sobrien   other code will catch a disk full though.  */
442918334Speter
443052558Sobrienstatic int
443150615Sobrienprint_single_switch (file, pos, max, indent, sep, term, type, name)
443250615Sobrien     FILE *file;
443350615Sobrien     int pos, max;
443452558Sobrien     const char *indent, *sep, *term, *type, *name;
443518334Speter{
443650615Sobrien  /* The ultrix fprintf returns 0 on success, so compute the result we want
443750615Sobrien     here since we need it for the following test.  */
443850615Sobrien  int len = strlen (sep) + strlen (type) + strlen (name);
443918334Speter
444050615Sobrien  if (pos != 0
444150615Sobrien      && pos + len > max)
444218334Speter    {
444350615Sobrien      fprintf (file, "%s", term);
444450615Sobrien      pos = 0;
444518334Speter    }
444650615Sobrien  if (pos == 0)
444750615Sobrien    {
444850615Sobrien      fprintf (file, "%s", indent);
444950615Sobrien      pos = strlen (indent);
445050615Sobrien    }
445150615Sobrien  fprintf (file, "%s%s%s", sep, type, name);
445250615Sobrien  pos += len;
445350615Sobrien  return pos;
445418334Speter}
445590282Sobrien
445650615Sobrien/* Print active target switches to FILE.
445750615Sobrien   POS is the current cursor position and MAX is the size of a "line".
445850615Sobrien   Each line begins with INDENT and ends with TERM.
445950615Sobrien   Each switch is separated from the next by SEP.  */
446018334Speter
446152558Sobrienstatic void
446250615Sobrienprint_switch_values (file, pos, max, indent, sep, term)
446350615Sobrien     FILE *file;
446450615Sobrien     int pos, max;
446552558Sobrien     const char *indent, *sep, *term;
446618334Speter{
446750615Sobrien  size_t j;
446850615Sobrien  char **p;
446918334Speter
447050615Sobrien  /* Print the options as passed.  */
447118334Speter
447250615Sobrien  pos = print_single_switch (file, pos, max, indent, *indent ? " " : "", term,
447352558Sobrien			     _("options passed: "), "");
447450615Sobrien
447550615Sobrien  for (p = &save_argv[1]; *p != NULL; p++)
447650615Sobrien    if (**p == '-')
447750615Sobrien      {
447850615Sobrien	/* Ignore these.  */
447950615Sobrien	if (strcmp (*p, "-o") == 0)
448050615Sobrien	  {
448150615Sobrien	    if (p[1] != NULL)
448250615Sobrien	      p++;
448350615Sobrien	    continue;
448450615Sobrien	  }
448550615Sobrien	if (strcmp (*p, "-quiet") == 0)
448650615Sobrien	  continue;
448750615Sobrien	if (strcmp (*p, "-version") == 0)
448850615Sobrien	  continue;
448950615Sobrien	if ((*p)[1] == 'd')
449050615Sobrien	  continue;
449150615Sobrien
449250615Sobrien	pos = print_single_switch (file, pos, max, indent, sep, term, *p, "");
449350615Sobrien      }
449450615Sobrien  if (pos > 0)
449550615Sobrien    fprintf (file, "%s", term);
449650615Sobrien
449750615Sobrien  /* Print the -f and -m options that have been enabled.
449850615Sobrien     We don't handle language specific options but printing argv
449950615Sobrien     should suffice.  */
450050615Sobrien
450150615Sobrien  pos = print_single_switch (file, 0, max, indent, *indent ? " " : "", term,
450252558Sobrien			     _("options enabled: "), "");
450350615Sobrien
450490282Sobrien  for (j = 0; j < ARRAY_SIZE (f_options); j++)
450518334Speter    if (*f_options[j].variable == f_options[j].on_value)
450650615Sobrien      pos = print_single_switch (file, pos, max, indent, sep, term,
450750615Sobrien				 "-f", f_options[j].string);
450818334Speter
450950615Sobrien  /* Print target specific options.  */
451018334Speter
451190282Sobrien  for (j = 0; j < ARRAY_SIZE (target_switches); j++)
451218334Speter    if (target_switches[j].name[0] != '\0'
451318334Speter	&& target_switches[j].value > 0
451418334Speter	&& ((target_switches[j].value & target_flags)
451518334Speter	    == target_switches[j].value))
451650615Sobrien      {
451750615Sobrien	pos = print_single_switch (file, pos, max, indent, sep, term,
451850615Sobrien				   "-m", target_switches[j].name);
451950615Sobrien      }
452018334Speter
452150615Sobrien#ifdef TARGET_OPTIONS
452290282Sobrien  for (j = 0; j < ARRAY_SIZE (target_options); j++)
452350615Sobrien    if (*target_options[j].variable != NULL)
452450615Sobrien      {
452550615Sobrien	char prefix[256];
452650615Sobrien	sprintf (prefix, "-m%s", target_options[j].prefix);
452750615Sobrien	pos = print_single_switch (file, pos, max, indent, sep, term,
452850615Sobrien				   prefix, *target_options[j].variable);
452950615Sobrien      }
453050615Sobrien#endif
453150615Sobrien
453250615Sobrien  fprintf (file, "%s", term);
453318334Speter}
453490282Sobrien
453590282Sobrien/* Open assembly code output file.  Do this even if -fsyntax-only is
453690282Sobrien   on, because then the driver will have provided the name of a
453790282Sobrien   temporary file or bit bucket for us.  NAME is the file specified on
453890282Sobrien   the command line, possibly NULL.  */
453990282Sobrienstatic void
454090282Sobrieninit_asm_output (name)
454190282Sobrien     const char *name;
454290282Sobrien{
454390282Sobrien  if (name == NULL && asm_file_name == 0)
454490282Sobrien    asm_out_file = stdout;
454590282Sobrien  else
454690282Sobrien    {
454790282Sobrien      if (asm_file_name == 0)
454890282Sobrien        {
454990282Sobrien          int len = strlen (dump_base_name);
455090282Sobrien          char *dumpname = (char *) xmalloc (len + 6);
455190282Sobrien          memcpy (dumpname, dump_base_name, len + 1);
455290282Sobrien          strip_off_ending (dumpname, len);
455390282Sobrien          strcat (dumpname, ".s");
455490282Sobrien          asm_file_name = dumpname;
455590282Sobrien        }
455690282Sobrien      if (!strcmp (asm_file_name, "-"))
455790282Sobrien        asm_out_file = stdout;
455890282Sobrien      else
455990282Sobrien        asm_out_file = fopen (asm_file_name, "w");
456090282Sobrien      if (asm_out_file == 0)
456190282Sobrien	fatal_io_error ("can't open %s for writing", asm_file_name);
456290282Sobrien    }
456350615Sobrien
456490282Sobrien#ifdef IO_BUFFER_SIZE
456590282Sobrien  setvbuf (asm_out_file, (char *) xmalloc (IO_BUFFER_SIZE),
456690282Sobrien           _IOFBF, IO_BUFFER_SIZE);
456790282Sobrien#endif
456850615Sobrien
456990282Sobrien  if (!flag_syntax_only)
457090282Sobrien    {
457190282Sobrien#ifdef ASM_FILE_START
457290282Sobrien      ASM_FILE_START (asm_out_file);
457390282Sobrien#endif
457490282Sobrien
457590282Sobrien#ifdef ASM_COMMENT_START
457690282Sobrien      if (flag_verbose_asm)
457790282Sobrien	{
457890282Sobrien	  /* Print the list of options in effect.  */
457990282Sobrien	  print_version (asm_out_file, ASM_COMMENT_START);
458090282Sobrien	  print_switch_values (asm_out_file, 0, MAX_LINE,
458190282Sobrien			       ASM_COMMENT_START, " ", "\n");
458290282Sobrien	  /* Add a blank line here so it appears in assembler output but not
458390282Sobrien	     screen output.  */
458490282Sobrien	  fprintf (asm_out_file, "\n");
458590282Sobrien	}
458690282Sobrien#endif
458790282Sobrien    }
458890282Sobrien}
458990282Sobrien
459090282Sobrien/* Initialization of the front end environment, before command line
459190282Sobrien   options are parsed.  Signal handlers, internationalization etc.
459290282Sobrien   ARGV0 is main's argv[0].  */
459390282Sobrienstatic void
459490282Sobriengeneral_init (argv0)
459590282Sobrien     char *argv0;
459650615Sobrien{
459790282Sobrien  char *p;
459890282Sobrien
459990282Sobrien  p = argv0 + strlen (argv0);
460090282Sobrien  while (p != argv0 && !IS_DIR_SEPARATOR (p[-1]))
460190282Sobrien    --p;
460290282Sobrien  progname = p;
460390282Sobrien
460490282Sobrien  xmalloc_set_program_name (progname);
460590282Sobrien
460690282Sobrien  gcc_init_libintl ();
460790282Sobrien
460890282Sobrien  /* Install handler for SIGFPE, which may be received while we do
460990282Sobrien     compile-time floating point arithmetic.  */
461090282Sobrien  signal (SIGFPE, float_signal);
461190282Sobrien
461290282Sobrien  /* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages.  */
461390282Sobrien#ifdef SIGSEGV
461490282Sobrien  signal (SIGSEGV, crash_signal);
461550615Sobrien#endif
461690282Sobrien#ifdef SIGILL
461790282Sobrien  signal (SIGILL, crash_signal);
461850615Sobrien#endif
461990282Sobrien#ifdef SIGBUS
462090282Sobrien  signal (SIGBUS, crash_signal);
462190282Sobrien#endif
462290282Sobrien#ifdef SIGABRT
462390282Sobrien  signal (SIGABRT, crash_signal);
462490282Sobrien#endif
462590282Sobrien#if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT)
462690282Sobrien  signal (SIGIOT, crash_signal);
462790282Sobrien#endif
462890282Sobrien
462990282Sobrien  /* Initialize the diagnostics reporting machinery, so option parsing
463090282Sobrien     can give warnings and errors.  */
463190282Sobrien  diagnostic_initialize (global_dc);
463250615Sobrien}
463390282Sobrien
463490282Sobrien/* Parse command line options and set default flag values, called
463590282Sobrien   after language-independent option-independent initialization.  Do
463690282Sobrien   minimal options processing.  Outputting diagnostics is OK, but GC
463790282Sobrien   and identifier hashtables etc. are not initialized yet.  */
463890282Sobrienstatic void
463990282Sobrienparse_options_and_default_flags (argc, argv)
464090282Sobrien     int argc;
464190282Sobrien     char **argv;
464290282Sobrien{
464390282Sobrien  int i;
464450615Sobrien
464590282Sobrien  /* Save in case md file wants to emit args as a comment.  */
464690282Sobrien  save_argc = argc;
464790282Sobrien  save_argv = argv;
464850615Sobrien
464990282Sobrien  /* Initialize register usage now so switches may override.  */
465090282Sobrien  init_reg_sets ();
465190282Sobrien
465290282Sobrien  /* Register the language-independent parameters.  */
465390282Sobrien  add_params (lang_independent_params, LAST_PARAM);
465490282Sobrien
465590282Sobrien  /* Perform language-specific options initialization.  */
465690282Sobrien  (*lang_hooks.init_options) ();
465790282Sobrien
465890282Sobrien  /* Scan to see what optimization level has been specified.  That will
465990282Sobrien     determine the default value of many flags.  */
466090282Sobrien  for (i = 1; i < argc; i++)
466190282Sobrien    {
466290282Sobrien      if (!strcmp (argv[i], "-O"))
466390282Sobrien	{
466490282Sobrien	  optimize = 1;
466590282Sobrien	  optimize_size = 0;
466690282Sobrien	}
466790282Sobrien      else if (argv[i][0] == '-' && argv[i][1] == 'O')
466890282Sobrien	{
466990282Sobrien	  /* Handle -Os, -O2, -O3, -O69, ...  */
467090282Sobrien	  char *p = &argv[i][2];
467190282Sobrien
467290282Sobrien	  if ((p[0] == 's') && (p[1] == 0))
467390282Sobrien	    {
467490282Sobrien	      optimize_size = 1;
467590282Sobrien
467690282Sobrien	      /* Optimizing for size forces optimize to be 2.  */
467790282Sobrien	      optimize = 2;
467890282Sobrien	    }
467990282Sobrien	  else
468090282Sobrien	    {
468190282Sobrien	      const int optimize_val = read_integral_parameter (p, p - 2, -1);
468290282Sobrien	      if (optimize_val != -1)
468390282Sobrien		{
468490282Sobrien		  optimize = optimize_val;
468590282Sobrien
468690282Sobrien#ifdef FORCE_OPTIMIZATION_DOWNGRADE
468790282Sobrien#warning FORCE_OPTIMIZATION_DOWNGRADE
468890282Sobrien		  if (optimize > FORCE_OPTIMIZATION_DOWNGRADE)
468990282Sobrien		    {
469090282Sobrien		      optimize = FORCE_OPTIMIZATION_DOWNGRADE;
469196289Sobrien		      warning ("\n***\n***\t-O%d converted to \"-O%d\" due to optimizer bugs on this platform\n***",
469290282Sobrien			      optimize_val,
469390282Sobrien			      FORCE_OPTIMIZATION_DOWNGRADE);
469490282Sobrien
469590282Sobrien		    }
469690282Sobrien#endif /*FORCE_OPTIMIZATION_DOWNGRADE*/
469790282Sobrien
4698103792Sobrien#if defined(TRY_WITHOUT_THIS__alpha__)
469990282Sobrien		  if (optimize > 1)
470090282Sobrien		    {
470196289Sobrien		      warning ("\n***\n***\tThe -O%d flag TRIGGERS KNOWN OPTIMIZER BUGS ON THIS PLATFORM\n***",
470290282Sobrien			      optimize_val);
470390282Sobrien		    }
470490282Sobrien#endif /*__alpha__*/
470590282Sobrien
470690282Sobrien		  optimize_size = 0;
470790282Sobrien		}
470890282Sobrien	    }
470990282Sobrien	}
471090282Sobrien    }
471190282Sobrien
471290282Sobrien  if (!optimize)
471390282Sobrien    {
471490282Sobrien      flag_merge_constants = 0;
471590282Sobrien    }
471690282Sobrien
471790282Sobrien  if (optimize >= 1)
471890282Sobrien    {
471990282Sobrien      flag_defer_pop = 1;
472090282Sobrien      flag_thread_jumps = 1;
472190282Sobrien#ifdef DELAY_SLOTS
472290282Sobrien      flag_delayed_branch = 1;
472390282Sobrien#endif
472490282Sobrien#ifdef CAN_DEBUG_WITHOUT_FP
472590282Sobrien      flag_omit_frame_pointer = 1;
472690282Sobrien#endif
472790282Sobrien      flag_guess_branch_prob = 1;
472890282Sobrien      flag_cprop_registers = 1;
472990282Sobrien    }
473090282Sobrien
473190282Sobrien  if (optimize >= 2)
473290282Sobrien    {
473390282Sobrien      flag_optimize_sibling_calls = 1;
473490282Sobrien      flag_cse_follow_jumps = 1;
473590282Sobrien      flag_cse_skip_blocks = 1;
473690282Sobrien      flag_gcse = 1;
473790282Sobrien      flag_expensive_optimizations = 1;
473890282Sobrien      flag_strength_reduce = 1;
473990282Sobrien      flag_rerun_cse_after_loop = 1;
474090282Sobrien      flag_rerun_loop_opt = 1;
474190282Sobrien      flag_caller_saves = 1;
474290282Sobrien      flag_force_mem = 1;
474390282Sobrien      flag_peephole2 = 1;
474490282Sobrien#ifdef INSN_SCHEDULING
474590282Sobrien      flag_schedule_insns = 1;
474690282Sobrien      flag_schedule_insns_after_reload = 1;
474790282Sobrien#endif
474890282Sobrien      flag_regmove = 1;
474990282Sobrien      flag_strict_aliasing = 1;
475090282Sobrien      flag_delete_null_pointer_checks = 1;
475190282Sobrien      flag_reorder_blocks = 1;
475290282Sobrien    }
475390282Sobrien
475490282Sobrien  if (optimize >= 3)
475590282Sobrien    {
475690282Sobrien      flag_inline_functions = 1;
475790282Sobrien      flag_rename_registers = 1;
475890282Sobrien    }
475990282Sobrien
476098573Sobrien  if (optimize_size)
476190282Sobrien    {
476290282Sobrien      align_loops = 1;
476390282Sobrien      align_jumps = 1;
476490282Sobrien      align_labels = 1;
476590282Sobrien      align_functions = 1;
476690282Sobrien    }
476790282Sobrien
476890282Sobrien  /* Initialize whether `char' is signed.  */
476990282Sobrien  flag_signed_char = DEFAULT_SIGNED_CHAR;
477090282Sobrien#ifdef DEFAULT_SHORT_ENUMS
477190282Sobrien  /* Initialize how much space enums occupy, by default.  */
477290282Sobrien  flag_short_enums = DEFAULT_SHORT_ENUMS;
477390282Sobrien#endif
477490282Sobrien
477590282Sobrien  /* Initialize target_flags before OPTIMIZATION_OPTIONS so the latter can
477690282Sobrien     modify it.  */
477790282Sobrien  target_flags = 0;
477890282Sobrien  set_target_switch ("");
477990282Sobrien
478090282Sobrien  /* Unwind tables are always present in an ABI-conformant IA-64
478190282Sobrien     object file, so the default should be ON.  */
478290282Sobrien#ifdef IA64_UNWIND_INFO
478390282Sobrien  flag_unwind_tables = IA64_UNWIND_INFO;
478490282Sobrien#endif
478590282Sobrien
478690282Sobrien#ifdef OPTIMIZATION_OPTIONS
478790282Sobrien  /* Allow default optimizations to be specified on a per-machine basis.  */
478890282Sobrien  OPTIMIZATION_OPTIONS (optimize, optimize_size);
478990282Sobrien#endif
479090282Sobrien
479190282Sobrien  /* Perform normal command line switch decoding.  */
479290282Sobrien  for (i = 1; i < argc;)
479390282Sobrien    {
479490282Sobrien      int lang_processed;
479590282Sobrien      int indep_processed;
479690282Sobrien
479790282Sobrien      /* Give the language a chance to decode the option for itself.  */
479890282Sobrien      lang_processed = (*lang_hooks.decode_option) (argc - i, argv + i);
479990282Sobrien
480090282Sobrien      if (lang_processed >= 0)
480190282Sobrien	/* Now see if the option also has a language independent meaning.
480290282Sobrien	   Some options are both language specific and language independent,
480390282Sobrien	   eg --help.  */
480490282Sobrien	indep_processed = independent_decode_option (argc - i, argv + i);
480590282Sobrien      else
480690282Sobrien	{
480790282Sobrien	  lang_processed = -lang_processed;
480890282Sobrien	  indep_processed = 0;
480990282Sobrien	}
481090282Sobrien
481190282Sobrien      if (lang_processed || indep_processed)
481290282Sobrien	i += MAX (lang_processed, indep_processed);
481390282Sobrien      else
481490282Sobrien	{
481590282Sobrien	  const char *option = NULL;
481690282Sobrien	  const char *lang = NULL;
481790282Sobrien	  unsigned int j;
481890282Sobrien
481990282Sobrien	  /* It is possible that the command line switch is not valid for the
482090282Sobrien	     current language, but it is valid for another language.  In order
482190282Sobrien	     to be compatible with previous versions of the compiler (which
482290282Sobrien	     did not issue an error message in this case) we check for this
482390282Sobrien	     possibility here.  If we do find a match, then if extra_warnings
482490282Sobrien	     is set we generate a warning message, otherwise we will just
482590282Sobrien	     ignore the option.  */
482690282Sobrien	  for (j = 0; j < ARRAY_SIZE (documented_lang_options); j++)
482790282Sobrien	    {
482890282Sobrien	      option = documented_lang_options[j].option;
482990282Sobrien
483090282Sobrien	      if (option == NULL)
483190282Sobrien		lang = documented_lang_options[j].description;
483290282Sobrien	      else if (! strncmp (argv[i], option, strlen (option)))
483390282Sobrien		break;
483490282Sobrien	    }
483590282Sobrien
483690282Sobrien	  if (j != ARRAY_SIZE (documented_lang_options))
483790282Sobrien	    {
483890282Sobrien	      if (extra_warnings)
483990282Sobrien		{
484090282Sobrien		  warning ("ignoring command line option '%s'", argv[i]);
484190282Sobrien		  if (lang)
484290282Sobrien		    warning
484390282Sobrien		      ("(it is valid for %s but not the selected language)",
484490282Sobrien		       lang);
484590282Sobrien		}
484690282Sobrien	    }
484790282Sobrien	  else if (argv[i][0] == '-' && argv[i][1] == 'g')
484890282Sobrien	    warning ("`%s': unknown or unsupported -g option", &argv[i][2]);
484990282Sobrien	  else
485090282Sobrien	    error ("unrecognized option `%s'", argv[i]);
485190282Sobrien
485290282Sobrien	  i++;
485390282Sobrien	}
485490282Sobrien    }
485590282Sobrien
485696289Sobrien  if (flag_no_inline == 2)
485796289Sobrien    flag_no_inline = 0;
485896289Sobrien  else
485996289Sobrien    flag_really_no_inline = flag_no_inline;
486096289Sobrien
486190282Sobrien  /* Set flag_no_inline before the post_options () hook.  The C front
486290282Sobrien     ends use it to determine tree inlining defaults.  FIXME: such
486390282Sobrien     code should be lang-independent when all front ends use tree
486490282Sobrien     inlining, in which case it, and this condition, should be moved
486590282Sobrien     to the top of process_options() instead.  */
486690282Sobrien  if (optimize == 0)
486790282Sobrien    {
486890282Sobrien      /* Inlining does not work if not optimizing,
486990282Sobrien	 so force it not to be done.  */
487090282Sobrien      flag_no_inline = 1;
487190282Sobrien      warn_inline = 0;
487290282Sobrien
487390282Sobrien      /* The c_decode_option function and decode_option hook set
487490282Sobrien	 this to `2' if -Wall is used, so we can avoid giving out
487590282Sobrien	 lots of errors for people who don't realize what -Wall does.  */
487690282Sobrien      if (warn_uninitialized == 1)
487790282Sobrien	warning ("-Wuninitialized is not supported without -O");
487890282Sobrien    }
487990282Sobrien
488096289Sobrien  if (flag_really_no_inline == 2)
488196289Sobrien    flag_really_no_inline = flag_no_inline;
488296289Sobrien
488390282Sobrien  /* All command line options have been parsed; allow the front end to
488490282Sobrien     perform consistency checks, etc.  */
488590282Sobrien  (*lang_hooks.post_options) ();
488690282Sobrien}
488790282Sobrien
488890282Sobrien/* Process the options that have been parsed.  */
488990282Sobrienstatic void
489090282Sobrienprocess_options ()
489150615Sobrien{
489290282Sobrien#ifdef OVERRIDE_OPTIONS
489390282Sobrien  /* Some machines may reject certain combinations of options.  */
489490282Sobrien  OVERRIDE_OPTIONS;
489590282Sobrien#endif
489690282Sobrien
489790282Sobrien  /* Set up the align_*_log variables, defaulting them to 1 if they
489890282Sobrien     were still unset.  */
489990282Sobrien  if (align_loops <= 0) align_loops = 1;
490090282Sobrien  if (align_loops_max_skip > align_loops || !align_loops)
490190282Sobrien    align_loops_max_skip = align_loops - 1;
490290282Sobrien  align_loops_log = floor_log2 (align_loops * 2 - 1);
490390282Sobrien  if (align_jumps <= 0) align_jumps = 1;
490490282Sobrien  if (align_jumps_max_skip > align_jumps || !align_jumps)
490590282Sobrien    align_jumps_max_skip = align_jumps - 1;
490690282Sobrien  align_jumps_log = floor_log2 (align_jumps * 2 - 1);
490790282Sobrien  if (align_labels <= 0) align_labels = 1;
490890282Sobrien  align_labels_log = floor_log2 (align_labels * 2 - 1);
490990282Sobrien  if (align_labels_max_skip > align_labels || !align_labels)
491090282Sobrien    align_labels_max_skip = align_labels - 1;
491190282Sobrien  if (align_functions <= 0) align_functions = 1;
491290282Sobrien  align_functions_log = floor_log2 (align_functions * 2 - 1);
491390282Sobrien
491490282Sobrien  /* Unrolling all loops implies that standard loop unrolling must also
491590282Sobrien     be done.  */
491690282Sobrien  if (flag_unroll_all_loops)
491790282Sobrien    flag_unroll_loops = 1;
491890282Sobrien  /* Loop unrolling requires that strength_reduction be on also.  Silently
491990282Sobrien     turn on strength reduction here if it isn't already on.  Also, the loop
492090282Sobrien     unrolling code assumes that cse will be run after loop, so that must
492190282Sobrien     be turned on also.  */
492290282Sobrien  if (flag_unroll_loops)
492390282Sobrien    {
492490282Sobrien      flag_strength_reduce = 1;
492590282Sobrien      flag_rerun_cse_after_loop = 1;
492690282Sobrien    }
492790282Sobrien
492890282Sobrien  if (flag_non_call_exceptions)
492990282Sobrien    flag_asynchronous_unwind_tables = 1;
493090282Sobrien  if (flag_asynchronous_unwind_tables)
493190282Sobrien    flag_unwind_tables = 1;
493290282Sobrien
493390282Sobrien  /* Warn about options that are not supported on this machine.  */
493490282Sobrien#ifndef INSN_SCHEDULING
493590282Sobrien  if (flag_schedule_insns || flag_schedule_insns_after_reload)
493690282Sobrien    warning ("instruction scheduling not supported on this target machine");
493790282Sobrien#endif
493890282Sobrien#ifndef DELAY_SLOTS
493990282Sobrien  if (flag_delayed_branch)
494090282Sobrien    warning ("this target machine does not have delayed branches");
494190282Sobrien#endif
494290282Sobrien
494390282Sobrien  /* Some operating systems do not allow profiling without a frame
494490282Sobrien     pointer.  */
494590282Sobrien  if (!TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
494690282Sobrien      && profile_flag
494790282Sobrien      && flag_omit_frame_pointer)
494890282Sobrien    {
494990282Sobrien      error ("profiling does not work without a frame pointer");
495090282Sobrien      flag_omit_frame_pointer = 0;
495190282Sobrien    }
495290282Sobrien
495390282Sobrien  user_label_prefix = USER_LABEL_PREFIX;
495490282Sobrien  if (flag_leading_underscore != -1)
495590282Sobrien    {
495690282Sobrien      /* If the default prefix is more complicated than "" or "_",
495790282Sobrien	 issue a warning and ignore this option.  */
495890282Sobrien      if (user_label_prefix[0] == 0 ||
495990282Sobrien	  (user_label_prefix[0] == '_' && user_label_prefix[1] == 0))
496090282Sobrien	{
496190282Sobrien	  user_label_prefix = flag_leading_underscore ? "_" : "";
496290282Sobrien	}
496390282Sobrien      else
496490282Sobrien	warning ("-f%sleading-underscore not supported on this target machine",
496590282Sobrien		 flag_leading_underscore ? "" : "no-");
496690282Sobrien    }
496790282Sobrien
496890282Sobrien  /* If we are in verbose mode, write out the version and maybe all the
496990282Sobrien     option flags in use.  */
497090282Sobrien  if (version_flag)
497190282Sobrien    {
497290282Sobrien      print_version (stderr, "");
497390282Sobrien      if (! quiet_flag)
497490282Sobrien	print_switch_values (stderr, 0, MAX_LINE, "", " ", "\n");
497590282Sobrien    }
497690282Sobrien
497790282Sobrien  if (! quiet_flag)
497890282Sobrien    time_report = 1;
497990282Sobrien
498090282Sobrien  if (flag_syntax_only)
498190282Sobrien    {
498290282Sobrien      write_symbols = NO_DEBUG;
498390282Sobrien      profile_flag = 0;
498490282Sobrien    }
498590282Sobrien
498690282Sobrien  /* Now we know write_symbols, set up the debug hooks based on it.
498790282Sobrien     By default we do nothing for debug output.  */
498890282Sobrien#if defined(DBX_DEBUGGING_INFO)
498950615Sobrien  if (write_symbols == DBX_DEBUG)
499090282Sobrien    debug_hooks = &dbx_debug_hooks;
499150615Sobrien#endif
499290282Sobrien#if defined(XCOFF_DEBUGGING_INFO)
499390282Sobrien  if (write_symbols == XCOFF_DEBUG)
499490282Sobrien    debug_hooks = &xcoff_debug_hooks;
499590282Sobrien#endif
499650615Sobrien#ifdef SDB_DEBUGGING_INFO
499750615Sobrien  if (write_symbols == SDB_DEBUG)
499890282Sobrien    debug_hooks = &sdb_debug_hooks;
499950615Sobrien#endif
500090282Sobrien#ifdef DWARF_DEBUGGING_INFO
500190282Sobrien  if (write_symbols == DWARF_DEBUG)
500290282Sobrien    debug_hooks = &dwarf_debug_hooks;
500390282Sobrien#endif
500490282Sobrien#ifdef DWARF2_DEBUGGING_INFO
500590282Sobrien  if (write_symbols == DWARF2_DEBUG)
500690282Sobrien    debug_hooks = &dwarf2_debug_hooks;
500790282Sobrien#endif
500890282Sobrien#ifdef VMS_DEBUGGING_INFO
500990282Sobrien  if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
501090282Sobrien    debug_hooks = &vmsdbg_debug_hooks;
501190282Sobrien#endif
501290282Sobrien
501390282Sobrien  /* If auxiliary info generation is desired, open the output file.
501490282Sobrien     This goes in the same directory as the source file--unlike
501590282Sobrien     all the other output files.  */
501690282Sobrien  if (flag_gen_aux_info)
501790282Sobrien    {
501890282Sobrien      aux_info_file = fopen (aux_info_file_name, "w");
501990282Sobrien      if (aux_info_file == 0)
502090282Sobrien	fatal_io_error ("can't open %s", aux_info_file_name);
502190282Sobrien    }
502290282Sobrien
502390282Sobrien  if (! targetm.have_named_sections)
502490282Sobrien    {
502590282Sobrien      if (flag_function_sections)
502690282Sobrien	{
502790282Sobrien	  warning ("-ffunction-sections not supported for this target");
502890282Sobrien	  flag_function_sections = 0;
502990282Sobrien	}
503090282Sobrien      if (flag_data_sections)
503190282Sobrien	{
503290282Sobrien	  warning ("-fdata-sections not supported for this target");
503390282Sobrien	  flag_data_sections = 0;
503490282Sobrien	}
503590282Sobrien    }
503690282Sobrien
503790282Sobrien  if (flag_function_sections && profile_flag)
503890282Sobrien    {
503990282Sobrien      warning ("-ffunction-sections disabled; it makes profiling impossible");
504090282Sobrien      flag_function_sections = 0;
504190282Sobrien    }
504290282Sobrien
504390282Sobrien#ifndef HAVE_prefetch
504490282Sobrien  if (flag_prefetch_loop_arrays)
504590282Sobrien    {
504690282Sobrien      warning ("-fprefetch-loop-arrays not supported for this target");
504790282Sobrien      flag_prefetch_loop_arrays = 0;
504890282Sobrien    }
504990282Sobrien#else
505090282Sobrien  if (flag_prefetch_loop_arrays && !HAVE_prefetch)
505190282Sobrien    {
505290282Sobrien      warning ("-fprefetch-loop-arrays not supported for this target (try -march switches)");
505390282Sobrien      flag_prefetch_loop_arrays = 0;
505490282Sobrien    }
505590282Sobrien#endif
505690282Sobrien
505790282Sobrien  /* This combination of options isn't handled for i386 targets and doesn't
505890282Sobrien     make much sense anyway, so don't allow it.  */
505990282Sobrien  if (flag_prefetch_loop_arrays && optimize_size)
506090282Sobrien    {
506190282Sobrien      warning ("-fprefetch-loop-arrays is not supported with -Os");
506290282Sobrien      flag_prefetch_loop_arrays = 0;
506390282Sobrien    }
506490282Sobrien
506590282Sobrien#ifndef OBJECT_FORMAT_ELF
506690282Sobrien  if (flag_function_sections && write_symbols != NO_DEBUG)
506790282Sobrien    warning ("-ffunction-sections may affect debugging on some targets");
506890282Sobrien#endif
506950615Sobrien}
507090282Sobrien
507190282Sobrien/* Language-independent initialization, before language-dependent
507290282Sobrien   initialization.  */
507390282Sobrienstatic void
507490282Sobrienlang_independent_init ()
507590282Sobrien{
507690282Sobrien  decl_printable_name = decl_name;
507790282Sobrien  lang_expand_expr = (lang_expand_expr_t) do_abort;
507850615Sobrien
507990282Sobrien  /* Set the language-dependent identifier size.  */
508090282Sobrien  tree_code_length[(int) IDENTIFIER_NODE]
508190282Sobrien    = ((lang_hooks.identifier_size - sizeof (struct tree_common)
508290282Sobrien	+ sizeof (tree) - 1) / sizeof (tree));
508350615Sobrien
508490282Sobrien  /* Initialize the garbage-collector, and string pools.  */
508590282Sobrien  init_ggc ();
508690282Sobrien  ggc_add_rtx_root (&stack_limit_rtx, 1);
508790282Sobrien  ggc_add_tree_root (&current_function_decl, 1);
508890282Sobrien  ggc_add_tree_root (&current_function_func_begin_label, 1);
508990282Sobrien
509090282Sobrien  init_stringpool ();
509190282Sobrien  init_obstacks ();
509290282Sobrien
509390282Sobrien  init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
509490282Sobrien		  || debug_info_level == DINFO_LEVEL_VERBOSE
509590282Sobrien#ifdef VMS_DEBUGGING_INFO
509690282Sobrien		    /* Enable line number info for traceback */
509790282Sobrien		    || debug_info_level > DINFO_LEVEL_NONE
509890282Sobrien#endif
509990282Sobrien		    || flag_test_coverage
510090282Sobrien		    || warn_notreached);
510190282Sobrien  init_regs ();
510290282Sobrien  init_alias_once ();
510390282Sobrien  init_stmt ();
510490282Sobrien  init_loop ();
510590282Sobrien  init_reload ();
510690282Sobrien  init_function_once ();
510790282Sobrien  init_stor_layout_once ();
510890282Sobrien  init_varasm_once ();
510990282Sobrien  init_EXPR_INSN_LIST_cache ();
511090282Sobrien
511190282Sobrien  /* The following initialization functions need to generate rtl, so
511290282Sobrien     provide a dummy function context for them.  */
511390282Sobrien  init_dummy_function_start ();
511490282Sobrien  init_expmed ();
511590282Sobrien  init_expr_once ();
511690282Sobrien  if (flag_caller_saves)
511790282Sobrien    init_caller_save ();
511890282Sobrien  expand_dummy_function_end ();
511990282Sobrien}
512090282Sobrien
512190282Sobrien/* Language-dependent initialization.  Returns non-zero on success.  */
512290282Sobrienstatic int
512390282Sobrienlang_dependent_init (name)
512490282Sobrien     const char *name;
512550615Sobrien{
512690282Sobrien  if (dump_base_name == 0)
512790282Sobrien    dump_base_name = name ? name : "gccdump";
512890282Sobrien
512990282Sobrien  /* Front-end initialization.  This hook can assume that GC,
513090282Sobrien     identifier hashes etc. are set up, but debug initialization is
513190282Sobrien     not done yet.  This routine must return the original filename
513290282Sobrien     (e.g. foo.i -> foo.c) so can correctly initialize debug output.  */
513390282Sobrien  name = (*lang_hooks.init) (name);
513490282Sobrien  if (name == NULL)
513590282Sobrien    return 0;
513690282Sobrien
513790282Sobrien  /* Is this duplication necessary?  */
513890282Sobrien  name = ggc_strdup (name);
513990282Sobrien  main_input_filename = input_filename = name;
514090282Sobrien  init_asm_output (name);
514190282Sobrien
514290282Sobrien  /* These create various _DECL nodes, so need to be called after the
514390282Sobrien     front end is initialized.  */
514490282Sobrien  init_eh ();
514590282Sobrien  init_optabs ();
514690282Sobrien
514790282Sobrien  /* Put an entry on the input file stack for the main input file.  */
514890282Sobrien  push_srcloc (input_filename, 0);
514990282Sobrien
515090282Sobrien  /* If dbx symbol table desired, initialize writing it and output the
515190282Sobrien     predefined types.  */
515290282Sobrien  timevar_push (TV_SYMOUT);
515390282Sobrien
515490282Sobrien#ifdef DWARF2_UNWIND_INFO
515590282Sobrien  if (dwarf2out_do_frame ())
515690282Sobrien    dwarf2out_frame_init ();
515790282Sobrien#endif
515890282Sobrien
515990282Sobrien  /* Now we have the correct original filename, we can initialize
516090282Sobrien     debug output.  */
516190282Sobrien  (*debug_hooks->init) (name);
516290282Sobrien
516390282Sobrien  timevar_pop (TV_SYMOUT);
516490282Sobrien
516590282Sobrien  return 1;
516650615Sobrien}
516790282Sobrien
516890282Sobrien/* Clean up: close opened files, etc.  */
516950615Sobrien
517090282Sobrienstatic void
517190282Sobrienfinalize ()
517290282Sobrien{
517390282Sobrien  /* Close the dump files.  */
517490282Sobrien  if (flag_gen_aux_info)
517590282Sobrien    {
517690282Sobrien      fclose (aux_info_file);
517790282Sobrien      if (errorcount)
517890282Sobrien	unlink (aux_info_file_name);
517990282Sobrien    }
518050615Sobrien
518190282Sobrien  /* Close non-debugging input and output files.  Take special care to note
518290282Sobrien     whether fclose returns an error, since the pages might still be on the
518390282Sobrien     buffer chain while the file is open.  */
518490282Sobrien
518590282Sobrien  if (asm_out_file)
518690282Sobrien    {
518790282Sobrien      if (ferror (asm_out_file) != 0)
518890282Sobrien	fatal_io_error ("error writing to %s", asm_file_name);
518990282Sobrien      if (fclose (asm_out_file) != 0)
519090282Sobrien	fatal_io_error ("error closing %s", asm_file_name);
519190282Sobrien    }
519290282Sobrien
519390282Sobrien  /* Do whatever is necessary to finish printing the graphs.  */
519490282Sobrien  if (graph_dump_format != no_graph)
519590282Sobrien    {
519690282Sobrien      int i;
519790282Sobrien
519890282Sobrien      for (i = 0; i < (int) DFI_MAX; ++i)
519990282Sobrien	if (dump_file[i].initialized && dump_file[i].graph_dump_p)
520090282Sobrien	  {
520190282Sobrien	    char seq[16];
520290282Sobrien	    char *suffix;
520390282Sobrien
520490282Sobrien	    sprintf (seq, DUMPFILE_FORMAT, i);
520590282Sobrien	    suffix = concat (seq, dump_file[i].extension, NULL);
520690282Sobrien	    finish_graph_dump_file (dump_base_name, suffix);
520790282Sobrien	    free (suffix);
520890282Sobrien	  }
520990282Sobrien    }
521090282Sobrien
521190282Sobrien  if (mem_report)
521290282Sobrien    {
521390282Sobrien      ggc_print_statistics ();
521490282Sobrien      stringpool_statistics ();
521590282Sobrien      dump_tree_statistics ();
521690282Sobrien    }
521790282Sobrien
521890282Sobrien  /* Free up memory for the benefit of leak detectors.  */
521990282Sobrien  free_reg_info ();
522090282Sobrien
522190282Sobrien  /* Language-specific end of compilation actions.  */
522290282Sobrien  (*lang_hooks.finish) ();
522390282Sobrien}
522490282Sobrien
522590282Sobrien/* Initialize the compiler, and compile the input file.  */
522690282Sobrienstatic void
522790282Sobriendo_compile ()
522850615Sobrien{
522990282Sobrien  /* The bulk of command line switch processing.  */
523090282Sobrien  process_options ();
523190282Sobrien
523290282Sobrien  /* We cannot start timing until after options are processed since that
523390282Sobrien     says if we run timers or not.  */
523490282Sobrien  init_timevar ();
523590282Sobrien  timevar_start (TV_TOTAL);
523690282Sobrien
523790282Sobrien  /* Language-independent initialization.  Also sets up GC, identifier
523890282Sobrien     hashes etc.  */
523990282Sobrien  lang_independent_init ();
524090282Sobrien
524190282Sobrien  /* Language-dependent initialization.  Returns true on success.  */
524290282Sobrien  if (lang_dependent_init (filename))
524390282Sobrien    compile_file ();
524490282Sobrien
524590282Sobrien  finalize ();
524690282Sobrien
524790282Sobrien  /* Stop timing and print the times.  */
524890282Sobrien  timevar_stop (TV_TOTAL);
524990282Sobrien  timevar_print (stderr);
525050615Sobrien}
525190282Sobrien
525290282Sobrien/* Entry point of cc1, cc1plus, jc1, f771, etc.
525390282Sobrien   Decode command args, then call compile_file.
525490282Sobrien   Exit code is FATAL_EXIT_CODE if can't open files or if there were
525590282Sobrien   any errors, or SUCCESS_EXIT_CODE if compilation succeeded.
525690282Sobrien
525790282Sobrien   It is not safe to call this function more than once.  */
525890282Sobrien
525990282Sobrienint
526090282Sobrientoplev_main (argc, argv)
526190282Sobrien     int argc;
526290282Sobrien     char **argv;
526390282Sobrien{
526490282Sobrien  hex_init ();
526590282Sobrien
526690282Sobrien  /* Initialization of GCC's environment, and diagnostics.  */
526790282Sobrien  general_init (argv [0]);
526890282Sobrien
526990282Sobrien  /* Parse the options and do minimal processing; basically just
527090282Sobrien     enough to default flags appropriately.  */
527190282Sobrien  parse_options_and_default_flags (argc, argv);
527290282Sobrien
527390282Sobrien  /* Exit early if we can (e.g. -help).  */
5274102796Skan  if (!errorcount && !exit_after_options)
527590282Sobrien    do_compile ();
527690282Sobrien
527790282Sobrien  if (errorcount || sorrycount)
527890282Sobrien    return (FATAL_EXIT_CODE);
527990282Sobrien
528090282Sobrien  return (SUCCESS_EXIT_CODE);
528190282Sobrien}
5282