1996-09-18 05:35:50 +00:00
/* Top level of GNU C compiler
2001-02-17 09:06:31 +00:00
Copyright ( C ) 1987 , 1988 , 1989 , 1992 , 1993 , 1994 , 1995 , 1996 , 1997 , 1998 ,
2002-02-06 04:59:39 +00:00
1999 , 2000 , 2001 , 2002 Free Software Foundation , Inc .
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
This file is part of GCC .
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
GCC is free software ; you can redistribute it and / or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation ; either version 2 , or ( at your option ) any later
version .
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
GCC is distributed in the hope that it will be useful , but WITHOUT ANY
WARRANTY ; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
for more details .
1996-09-18 05:35:50 +00:00
You should have received a copy of the GNU General Public License
2002-02-06 04:59:39 +00:00
along with GCC ; see the file COPYING . If not , write to the Free
Software Foundation , 59 Temple Place - Suite 330 , Boston , MA
02111 - 1307 , USA . */
1996-09-18 05:35:50 +00:00
1999-10-27 09:31:52 +00:00
/* $FreeBSD$ */
1996-09-18 05:35:50 +00:00
/* This is the top level of cc1/c++.
It parses command args , opens files , invokes the various passes
in the proper order , and counts the time used by each .
Error messages and low - level interface to malloc also handled here . */
# include "config.h"
1999-08-30 04:01:02 +00:00
# undef FLOAT /* This is for hpux. They should change hpux. */
# undef FFS /* Some systems define this in param.h. */
# include "system.h"
1996-09-18 05:35:50 +00:00
# include <signal.h>
# include <setjmp.h>
1999-08-30 04:01:02 +00:00
# ifdef HAVE_SYS_RESOURCE_H
# include <sys / resource.h>
1996-09-18 05:35:50 +00:00
# endif
1999-08-30 04:01:02 +00:00
# ifdef HAVE_SYS_TIMES_H
# include <sys / times.h>
1996-09-18 05:35:50 +00:00
# endif
# include "input.h"
# include "tree.h"
# include "rtl.h"
2002-02-06 04:59:39 +00:00
# include "tm_p.h"
1996-09-18 05:35:50 +00:00
# include "flags.h"
# include "insn-attr.h"
1999-08-30 04:01:02 +00:00
# include "insn-config.h"
2002-02-06 04:59:39 +00:00
# include "insn-flags.h"
# include "hard-reg-set.h"
1999-08-30 04:01:02 +00:00
# include "recog.h"
1996-09-18 05:35:50 +00:00
# include "output.h"
1999-08-30 04:01:02 +00:00
# include "except.h"
2002-02-06 04:59:39 +00:00
# include "function.h"
1999-08-30 04:01:02 +00:00
# include "toplev.h"
1999-10-27 09:31:52 +00:00
# include "expr.h"
# include "basic-block.h"
# include "intl.h"
2002-02-06 04:59:39 +00:00
# include "ggc.h"
# include "graph.h"
# include "loop.h"
# include "regs.h"
# include "timevar.h"
# include "diagnostic.h"
# include "ssa.h"
# include "params.h"
# include "reload.h"
# include "dwarf2asm.h"
# include "integrate.h"
# include "debug.h"
# include "target.h"
# include "langhooks.h"
1999-08-30 04:01:02 +00:00
# if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
# include "dwarf2out.h"
# endif
# if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
# include "dbxout.h"
# endif
# ifdef SDB_DEBUGGING_INFO
# include "sdbout.h"
# endif
1996-09-18 05:35:50 +00:00
# ifdef XCOFF_DEBUGGING_INFO
2002-02-06 04:59:39 +00:00
# include "xcoffout.h" /* Needed for external data
declarations for e . g . AIX 4. x . */
# endif
# ifdef HALF_PIC_DEBUG
# include "halfpic.h"
1996-09-18 05:35:50 +00:00
# endif
/* Carry information from ASM_DECLARE_OBJECT_NAME
to ASM_FINISH_DECLARE_OBJECT . */
extern int size_directive_output ;
extern tree last_assemble_variable_decl ;
2002-02-06 04:59:39 +00:00
static void general_init PARAMS ( ( char * ) ) ;
static void parse_options_and_default_flags PARAMS ( ( int , char * * ) ) ;
static void do_compile PARAMS ( ( void ) ) ;
static void process_options PARAMS ( ( void ) ) ;
static void lang_independent_init PARAMS ( ( void ) ) ;
static int lang_dependent_init PARAMS ( ( const char * ) ) ;
static void init_asm_output PARAMS ( ( const char * ) ) ;
static void finalize PARAMS ( ( void ) ) ;
static void set_target_switch PARAMS ( ( const char * ) ) ;
static const char * decl_name PARAMS ( ( tree , int ) ) ;
static void float_signal PARAMS ( ( int ) ) ATTRIBUTE_NORETURN ;
static void crash_signal PARAMS ( ( int ) ) ATTRIBUTE_NORETURN ;
static void set_float_handler PARAMS ( ( jmp_buf ) ) ;
static void compile_file PARAMS ( ( void ) ) ;
static void display_help PARAMS ( ( void ) ) ;
static void display_target_options PARAMS ( ( void ) ) ;
static void decode_d_option PARAMS ( ( const char * ) ) ;
static int decode_f_option PARAMS ( ( const char * ) ) ;
static int decode_W_option PARAMS ( ( const char * ) ) ;
static int decode_g_option PARAMS ( ( const char * ) ) ;
static unsigned int independent_decode_option PARAMS ( ( int , char * * ) ) ;
static void print_version PARAMS ( ( FILE * , const char * ) ) ;
static int print_single_switch PARAMS ( ( FILE * , int , int , const char * ,
1999-10-27 09:31:52 +00:00
const char * , const char * ,
const char * , const char * ) ) ;
2002-02-06 04:59:39 +00:00
static void print_switch_values PARAMS ( ( FILE * , int , int , const char * ,
1999-10-27 09:31:52 +00:00
const char * , const char * ) ) ;
1999-08-30 04:01:02 +00:00
/* Length of line when printing switch values. */
# define MAX_LINE 75
1996-09-18 05:35:50 +00:00
/* Name of program invoked, sans directories. */
2002-02-06 04:59:39 +00:00
const char * progname ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Copy of arguments to toplev_main. */
1996-09-18 05:35:50 +00:00
int save_argc ;
char * * save_argv ;
/* Name of current original source file (what was input to cpp).
This comes from each # - command in the actual input . */
2002-02-06 04:59:39 +00:00
const char * input_filename ;
1996-09-18 05:35:50 +00:00
/* Name of top-level original source file (what was input to cpp).
This comes from the # - command at the beginning of the actual input .
If there isn ' t any there , then this is the cc1 input file name . */
2002-02-06 04:59:39 +00:00
const char * main_input_filename ;
1996-09-18 05:35:50 +00:00
/* Current line number in real source file. */
int lineno ;
1999-10-27 09:31:52 +00:00
/* Nonzero if it is unsafe to create any new pseudo registers. */
int no_new_pseudos ;
1996-09-18 05:35:50 +00:00
/* Stack of currently pending input files. */
struct file_stack * input_file_stack ;
/* Incremented on each change to input_file_stack. */
int input_file_stack_tick ;
/* Name to use as base of names for dump output files. */
1999-10-27 09:31:52 +00:00
const char * dump_base_name ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Format to use to print dumpfile index value */
# ifndef DUMPFILE_FORMAT
# define DUMPFILE_FORMAT ".%02d."
# endif
1996-09-18 05:35:50 +00:00
/* Bit flags that specify the machine subtype we are compiling for.
Bits are tested using macros TARGET_ . . . defined in the tm . h file
and set by ` - m . . . ' switches . Must be defined in rtlanal . c . */
extern int target_flags ;
2002-02-06 04:59:39 +00:00
/* Debug hooks - dependent upon command line options. */
struct gcc_debug_hooks * debug_hooks = & do_nothing_debug_hooks ;
/* Describes a dump file. */
struct dump_file_info
{
/* The unique extension to apply, e.g. ".jump". */
const char * const extension ;
/* The -d<c> character that enables this dump file. */
char const debug_switch ;
/* True if there is a corresponding graph dump file. */
char const graph_dump_p ;
/* True if the user selected this dump. */
char enabled ;
/* True if the files have been initialized (ie truncated). */
char initialized ;
} ;
/* Enumerate the extant dump files. */
enum dump_file_index
{
DFI_rtl ,
DFI_sibling ,
DFI_eh ,
DFI_jump ,
DFI_ssa ,
DFI_ssa_ccp ,
DFI_ssa_dce ,
DFI_ussa ,
DFI_cse ,
DFI_addressof ,
DFI_gcse ,
DFI_loop ,
DFI_cse2 ,
DFI_cfg ,
DFI_bp ,
DFI_life ,
DFI_combine ,
DFI_ce ,
DFI_regmove ,
DFI_sched ,
DFI_lreg ,
DFI_greg ,
DFI_postreload ,
DFI_flow2 ,
DFI_peephole2 ,
DFI_rnreg ,
DFI_ce2 ,
DFI_sched2 ,
DFI_stack ,
DFI_bbro ,
DFI_mach ,
DFI_dbr ,
DFI_MAX
} ;
/* Describes all the dump files. Should be kept in order of the
pass and in sync with dump_file_index above .
Remaining - d letters :
" o q u "
" H JK OPQ TUV YZ "
*/
static struct dump_file_info dump_file [ DFI_MAX ] =
{
{ " rtl " , ' r ' , 0 , 0 , 0 } ,
{ " sibling " , ' i ' , 0 , 0 , 0 } ,
{ " eh " , ' h ' , 0 , 0 , 0 } ,
{ " jump " , ' j ' , 0 , 0 , 0 } ,
{ " ssa " , ' e ' , 1 , 0 , 0 } ,
{ " ssaccp " , ' W ' , 1 , 0 , 0 } ,
{ " ssadce " , ' X ' , 1 , 0 , 0 } ,
{ " ussa " , ' e ' , 1 , 0 , 0 } , /* Yes, duplicate enable switch. */
{ " cse " , ' s ' , 0 , 0 , 0 } ,
{ " addressof " , ' F ' , 0 , 0 , 0 } ,
{ " gcse " , ' G ' , 1 , 0 , 0 } ,
{ " loop " , ' L ' , 1 , 0 , 0 } ,
{ " cse2 " , ' t ' , 1 , 0 , 0 } ,
{ " cfg " , ' f ' , 1 , 0 , 0 } ,
{ " bp " , ' b ' , 1 , 0 , 0 } ,
{ " life " , ' f ' , 1 , 0 , 0 } , /* Yes, duplicate enable switch. */
{ " combine " , ' c ' , 1 , 0 , 0 } ,
{ " ce " , ' C ' , 1 , 0 , 0 } ,
{ " regmove " , ' N ' , 1 , 0 , 0 } ,
{ " sched " , ' S ' , 1 , 0 , 0 } ,
{ " lreg " , ' l ' , 1 , 0 , 0 } ,
{ " greg " , ' g ' , 1 , 0 , 0 } ,
{ " postreload " , ' o ' , 1 , 0 , 0 } ,
{ " flow2 " , ' w ' , 1 , 0 , 0 } ,
{ " peephole2 " , ' z ' , 1 , 0 , 0 } ,
{ " rnreg " , ' n ' , 1 , 0 , 0 } ,
{ " ce2 " , ' E ' , 1 , 0 , 0 } ,
{ " sched2 " , ' R ' , 1 , 0 , 0 } ,
{ " stack " , ' k ' , 1 , 0 , 0 } ,
{ " bbro " , ' B ' , 1 , 0 , 0 } ,
{ " mach " , ' M ' , 1 , 0 , 0 } ,
{ " dbr " , ' d ' , 0 , 0 , 0 } ,
} ;
static int open_dump_file PARAMS ( ( enum dump_file_index , tree ) ) ;
static void close_dump_file PARAMS ( ( enum dump_file_index ,
void ( * ) ( FILE * , rtx ) , rtx ) ) ;
/* Other flags saying which kinds of debugging dump have been requested. */
int rtl_dump_and_exit ;
int flag_print_asm_name ;
static int version_flag ;
static char * filename ;
1999-10-27 09:31:52 +00:00
enum graph_dump_types graph_dump_format ;
1996-09-18 05:35:50 +00:00
/* Name for output file of assembly code, specified with -o. */
char * asm_file_name ;
/* Value of the -G xx switch, and whether it was passed or not. */
int g_switch_value ;
int g_switch_set ;
/* Type(s) of debugging information we are producing (if any).
See flags . h for the definitions of the different possible
types of debugging information . */
enum debug_info_type write_symbols = NO_DEBUG ;
/* Level of debugging information we are producing. See flags.h
for the definitions of the different possible levels . */
enum debug_info_level debug_info_level = DINFO_LEVEL_NONE ;
/* Nonzero means use GNU-only extensions in the generated symbolic
debugging information . */
/* Currently, this only has an effect when write_symbols is set to
DBX_DEBUG , XCOFF_DEBUG , or DWARF_DEBUG . */
int use_gnu_debug_info_extensions = 0 ;
/* Nonzero means do optimizations. -O.
Particular numeric values stand for particular amounts of optimization ;
thus , - O2 stores 2 here . However , the optimizations beyond the basic
ones are not controlled directly by this variable . Instead , they are
controlled by individual ` flag_ . . . ' variables that are defaulted
based on this variable . */
int optimize = 0 ;
1999-08-30 04:01:02 +00:00
/* Nonzero means optimize for size. -Os.
The only valid values are zero and non - zero . When optimize_size is
non - zero , optimize defaults to 2 , but certain individual code
bloating optimizations are disabled . */
int optimize_size = 0 ;
2002-02-06 04:59:39 +00:00
/* Nonzero if we should exit after parsing options. */
static int exit_after_options = 0 ;
/* The FUNCTION_DECL for the function currently being compiled,
or 0 if between functions . */
tree current_function_decl ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Set to the FUNC_BEGIN label of the current function, or NULL_TREE
if none . */
tree current_function_func_begin_label ;
1996-09-18 05:35:50 +00:00
1999-08-30 04:01:02 +00:00
/* Pointer to function to compute the name to use to print a declaration.
DECL is the declaration in question .
VERBOSITY determines what information will be printed :
0 : DECL_NAME , demangled as necessary .
1 : and scope information .
2 : and any other information that might be interesting , such as function
parameter types in C + + . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
const char * ( * decl_printable_name ) PARAMS ( ( tree , int ) ) ;
1996-09-18 05:35:50 +00:00
/* Pointer to function to compute rtl for a language-specific tree code. */
1999-10-27 09:31:52 +00:00
typedef rtx ( * lang_expand_expr_t )
2002-02-06 04:59:39 +00:00
PARAMS ( ( union tree_node * , rtx , enum machine_mode ,
1999-10-27 09:31:52 +00:00
enum expand_modifier modifier ) ) ;
1996-09-18 05:35:50 +00:00
1999-10-27 09:31:52 +00:00
lang_expand_expr_t lang_expand_expr = 0 ;
1996-09-18 05:35:50 +00:00
1999-10-27 09:31:52 +00:00
/* Pointer to function to finish handling an incomplete decl at the
end of compilation . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
void ( * incomplete_decl_finalize_hook ) PARAMS ( ( tree ) ) = 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Nonzero if doing dwarf2 duplicate elimination. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
int flag_eliminate_dwarf2_dups = 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Nonzero if generating code to do profiling. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
int profile_flag = 0 ;
1996-09-18 05:35:50 +00:00
1999-08-30 04:01:02 +00:00
/* Nonzero if generating code to profile program flow graph arcs. */
int profile_arc_flag = 0 ;
/* Nonzero if generating info for gcov to calculate line test coverage. */
int flag_test_coverage = 0 ;
/* Nonzero indicates that branch taken probabilities should be calculated. */
int flag_branch_probabilities = 0 ;
2002-02-06 04:59:39 +00:00
/* Nonzero if basic blocks should be reordered. */
int flag_reorder_blocks = 0 ;
/* Nonzero if registers should be renamed. */
int flag_rename_registers = 0 ;
int flag_cprop_registers = 0 ;
1996-09-18 05:35:50 +00:00
/* Nonzero for -pedantic switch: warn about anything
that standard spec forbids . */
int pedantic = 0 ;
/* Temporarily suppress certain warnings.
This is set while reading code from a system header file . */
int in_system_header = 0 ;
2002-02-06 04:59:39 +00:00
/* Don't print functions as they are compiled. -quiet. */
int quiet_flag = 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Print times taken by the various passes. -ftime-report. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
int time_report = 0 ;
/* Print memory still in use at end of compilation (which may have little
to do with peak memory consumption ) . - fmem - report . */
int mem_report = 0 ;
/* Non-zero means to collect statistics which might be expensive
and to print them when we are done . */
int flag_detailed_statistics = 0 ;
1996-09-18 05:35:50 +00:00
/* -f flags. */
/* Nonzero means `char' should be signed. */
int flag_signed_char ;
/* Nonzero means give an enum type only as many bytes as it needs. */
int flag_short_enums ;
/* Nonzero for -fcaller-saves: allocate values in regs that need to
be saved across function calls , if that produces overall better code .
Optional now , so people can test it . */
# ifdef DEFAULT_CALLER_SAVES
int flag_caller_saves = 1 ;
# else
int flag_caller_saves = 0 ;
# endif
/* Nonzero if structures and unions should be returned in memory.
This should only be defined if compatibility with another compiler or
with an ABI is needed , because it results in slower code . */
# ifndef DEFAULT_PCC_STRUCT_RETURN
# define DEFAULT_PCC_STRUCT_RETURN 1
# endif
/* Nonzero for -fpcc-struct-return: return values the same way PCC does. */
int flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN ;
/* Nonzero for -fforce-mem: load memory value into a register
before arithmetic on it . This makes better cse but slower compilation . */
int flag_force_mem = 0 ;
/* Nonzero for -fforce-addr: load memory address into a register before
reference to memory . This makes better cse but slower compilation . */
int flag_force_addr = 0 ;
/* Nonzero for -fdefer-pop: don't pop args after each function call;
instead save them up to pop many calls ' args with one insns . */
int flag_defer_pop = 0 ;
/* Nonzero for -ffloat-store: don't allocate floats and doubles
in extended - precision registers . */
int flag_float_store = 0 ;
/* Nonzero for -fcse-follow-jumps:
have cse follow jumps to do a more extensive job . */
int flag_cse_follow_jumps ;
/* Nonzero for -fcse-skip-blocks:
have cse follow a branch around a block . */
int flag_cse_skip_blocks ;
/* Nonzero for -fexpensive-optimizations:
perform miscellaneous relatively - expensive optimizations . */
int flag_expensive_optimizations ;
/* Nonzero for -fthread-jumps:
have jump optimize output of loop . */
int flag_thread_jumps ;
/* Nonzero enables strength-reduction in loop.c. */
int flag_strength_reduce = 0 ;
/* Nonzero enables loop unrolling in unroll.c. Only loops for which the
number of iterations can be calculated at compile - time ( UNROLL_COMPLETELY ,
UNROLL_MODULO ) or at run - time ( preconditioned to be UNROLL_MODULO ) are
unrolled . */
int flag_unroll_loops ;
/* Nonzero enables loop unrolling in unroll.c. All loops are unrolled.
This is generally not a win . */
int flag_unroll_all_loops ;
2002-02-06 04:59:39 +00:00
/* Nonzero enables prefetch optimizations for arrays in loops. */
int flag_prefetch_loop_arrays ;
1999-08-30 04:01:02 +00:00
/* Nonzero forces all invariant computations in loops to be moved
2002-02-06 04:59:39 +00:00
outside the loop . */
1999-08-30 04:01:02 +00:00
int flag_move_all_movables = 0 ;
/* Nonzero forces all general induction variables in loops to be
2002-02-06 04:59:39 +00:00
strength reduced . */
1999-08-30 04:01:02 +00:00
int flag_reduce_all_givs = 0 ;
/* Nonzero to perform full register move optimization passes. This is the
default for - O2 . */
int flag_regmove = 0 ;
1996-09-18 05:35:50 +00:00
/* Nonzero for -fwritable-strings:
store string constants in data segment and don ' t uniquize them . */
int flag_writable_strings = 0 ;
/* Nonzero means don't put addresses of constant functions in registers.
Used for compiling the Unix kernel , where strange substitutions are
done on the assembly output . */
int flag_no_function_cse = 0 ;
/* Nonzero for -fomit-frame-pointer:
don ' t make a frame pointer in simple functions that don ' t require one . */
int flag_omit_frame_pointer = 0 ;
1999-08-30 04:01:02 +00:00
/* Nonzero means place each function into its own section on those platforms
which support arbitrary section names and unlimited numbers of sections . */
int flag_function_sections = 0 ;
1999-10-27 09:31:52 +00:00
/* ... and similar for data. */
2002-02-06 04:59:39 +00:00
1999-10-27 09:31:52 +00:00
int flag_data_sections = 0 ;
1996-09-18 05:35:50 +00:00
/* Nonzero to inhibit use of define_optimization peephole opts. */
int flag_no_peephole = 0 ;
2002-02-06 04:59:39 +00:00
/* Nonzero allows GCC to optimize sibling and tail recursive calls. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
int flag_optimize_sibling_calls = 0 ;
1996-09-18 05:35:50 +00:00
1999-10-27 09:31:52 +00:00
/* Nonzero means the front end generally wants `errno' maintained by math
2002-02-06 04:59:39 +00:00
operations , like built - in SQRT . */
1999-10-27 09:31:52 +00:00
int flag_errno_math = 1 ;
2002-02-06 04:59:39 +00:00
/* Nonzero means that unsafe floating-point math optimizations are allowed
for the sake of speed . IEEE compliance is not guaranteed , and operations
are allowed to assume that their arguments and results are " normal "
( e . g . , nonnegative for SQRT ) . */
int flag_unsafe_math_optimizations = 0 ;
/* Zero means that floating-point math operations cannot generate a
( user - visible ) trap . This is the case , for example , in nonstop
IEEE 754 arithmetic . */
int flag_trapping_math = 1 ;
1999-10-27 09:31:52 +00:00
/* 0 means straightforward implementation of complex divide acceptable.
1 means wide ranges of inputs must work for complex divide .
2002-02-06 04:59:39 +00:00
2 means C99 - like requirements for complex divide ( not yet implemented ) . */
1999-10-27 09:31:52 +00:00
int flag_complex_divide_method = 0 ;
1996-09-18 05:35:50 +00:00
/* Nonzero means all references through pointers are volatile. */
int flag_volatile ;
1999-10-27 09:31:52 +00:00
/* Nonzero means treat all global and extern variables as volatile. */
1996-09-18 05:35:50 +00:00
int flag_volatile_global ;
1999-10-27 09:31:52 +00:00
/* Nonzero means treat all static variables as volatile. */
int flag_volatile_static ;
1996-09-18 05:35:50 +00:00
/* Nonzero means just do syntax checking; don't output anything. */
int flag_syntax_only = 0 ;
1999-08-30 04:01:02 +00:00
/* Nonzero means perform global cse. */
static int flag_gcse ;
2002-02-06 04:59:39 +00:00
/* Nonzero means to use global dataflow analysis to eliminate
useless null pointer tests . */
static int flag_delete_null_pointer_checks ;
/* Nonzero means to do the enhanced load motion during gcse, which trys
to hoist loads by not killing them when a store to the same location
is seen . */
int flag_gcse_lm = 1 ;
/* Nonzero means to perform store motion after gcse, which will try to
move stores closer to the exit block . Its not very effective without
flag_gcse_lm . */
int flag_gcse_sm = 1 ;
1996-09-18 05:35:50 +00:00
/* Nonzero means to rerun cse after loop optimization. This increases
compilation time about 20 % and picks up a few more common expressions . */
static int flag_rerun_cse_after_loop ;
1999-08-30 04:01:02 +00:00
/* Nonzero means to run loop optimizations twice. */
int flag_rerun_loop_opt ;
1996-09-18 05:35:50 +00:00
/* Nonzero for -finline-functions: ok to inline functions that look like
good inline candidates . */
int flag_inline_functions ;
/* Nonzero for -fkeep-inline-functions: even if we make a function
go inline everywhere , keep its definition around for debugging
purposes . */
int flag_keep_inline_functions ;
/* Nonzero means that functions will not be inlined. */
2002-05-09 22:15:04 +00:00
int flag_no_inline = 2 ;
/* Nonzero means that we don't want inlining by virtue of -fno-inline,
not just because the tree inliner turned us off . */
int flag_really_no_inline = 2 ;
1996-09-18 05:35:50 +00:00
1999-08-30 04:01:02 +00:00
/* Nonzero means that we should emit static const variables
regardless of whether or not optimization is turned on . */
int flag_keep_static_consts = 1 ;
1996-09-18 05:35:50 +00:00
/* Nonzero means we should be saving declaration info into a .X file. */
int flag_gen_aux_info = 0 ;
/* Specified name of aux-info file. */
static char * aux_info_file_name ;
/* Nonzero means make the text shared if supported. */
int flag_shared_data ;
/* Nonzero means schedule into delayed branch slots if supported. */
int flag_delayed_branch ;
/* Nonzero if we are compiling pure (sharable) code.
Value is 1 if we are doing reasonable ( i . e . simple
offset into offset table ) pic . Value is 2 if we can
only perform register offsets . */
int flag_pic ;
1999-08-30 04:01:02 +00:00
/* Nonzero means generate extra code for exception handling and enable
exception handling . */
int flag_exceptions ;
2002-02-06 04:59:39 +00:00
/* Nonzero means generate frame unwind info table when supported. */
int flag_unwind_tables = 0 ;
/* Nonzero means generate frame unwind info table exact at each insn boundary */
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
int flag_asynchronous_unwind_tables = 0 ;
1999-08-30 04:01:02 +00:00
/* Nonzero means don't place uninitialized global data in common storage
by default . */
1996-09-18 05:35:50 +00:00
int flag_no_common ;
/* Nonzero means pretend it is OK to examine bits of target floats,
even if that isn ' t true . The resulting code will have incorrect constants ,
but the same series of instructions that the native compiler would make . */
int flag_pretend_float ;
/* Nonzero means change certain warnings into errors.
Usually these are warnings about failure to conform to some standard . */
int flag_pedantic_errors = 0 ;
/* flag_schedule_insns means schedule insns within basic blocks (before
local_alloc ) .
flag_schedule_insns_after_reload means schedule insns after
global_alloc . */
int flag_schedule_insns = 0 ;
int flag_schedule_insns_after_reload = 0 ;
1999-08-30 04:01:02 +00:00
/* The following flags have effect only for scheduling before register
allocation :
flag_schedule_interblock means schedule insns accross basic blocks .
flag_schedule_speculative means allow speculative motion of non - load insns .
flag_schedule_speculative_load means allow speculative motion of some
load insns .
flag_schedule_speculative_load_dangerous allows speculative motion of more
load insns . */
int flag_schedule_interblock = 1 ;
int flag_schedule_speculative = 1 ;
int flag_schedule_speculative_load = 0 ;
int flag_schedule_speculative_load_dangerous = 0 ;
2002-02-06 04:59:39 +00:00
int flag_single_precision_constant ;
/* flag_branch_on_count_reg means try to replace add-1,compare,branch tupple
by a cheaper branch on a count register . */
int flag_branch_on_count_reg = 1 ;
1999-08-30 04:01:02 +00:00
1996-09-18 05:35:50 +00:00
/* -finhibit-size-directive inhibits output of .size for ELF.
2002-02-06 04:59:39 +00:00
This is used only for compiling crtstuff . c ,
1996-09-18 05:35:50 +00:00
and it may be extended to other effects
needed for crtstuff . c on other systems . */
int flag_inhibit_size_directive = 0 ;
/* -fverbose-asm causes extra commentary information to be produced in
the generated assembly code ( to make it more readable ) . This option
is generally only of use to those who actually need to read the
1999-08-30 04:01:02 +00:00
generated assembly code ( perhaps while debugging the compiler itself ) .
- fno - verbose - asm , the default , causes the extra information
to be omitted and is useful when comparing two assembler files . */
1996-09-18 05:35:50 +00:00
int flag_verbose_asm = 0 ;
1999-08-30 04:01:02 +00:00
/* -dA causes debug commentary information to be produced in
the generated assembly code ( to make it more readable ) . This option
is generally only of use to those who actually need to read the
generated assembly code ( perhaps while debugging the compiler itself ) .
Currently , this switch is only used by dwarfout . c ; however , it is intended
to be a catchall for printing debug information in the assembler file . */
int flag_debug_asm = 0 ;
2002-02-06 04:59:39 +00:00
/* -dP causes the rtl to be emitted as a comment in assembly. */
int flag_dump_rtl_in_asm = 0 ;
1996-09-18 05:35:50 +00:00
/* -fgnu-linker specifies use of the GNU linker for initializations.
( Or , more generally , a linker that handles initializations . )
- fno - gnu - linker says that collect2 will be used . */
# ifdef USE_COLLECT2
int flag_gnu_linker = 0 ;
# else
int flag_gnu_linker = 1 ;
# endif
2002-02-06 04:59:39 +00:00
/* Enable SSA. */
int flag_ssa = 0 ;
/* Enable ssa conditional constant propagation. */
int flag_ssa_ccp = 0 ;
/* Enable ssa aggressive dead code elimination. */
int flag_ssa_dce = 0 ;
/* Tag all structures with __attribute__(packed). */
1996-09-18 05:35:50 +00:00
int flag_pack_struct = 0 ;
1998-08-24 06:33:52 +00:00
/* Nonzero means that -Wformat accepts certain system-dependent formats. */
int flag_format_extensions = 0 ;
1999-08-30 04:01:02 +00:00
/* Emit code to check for stack overflow; also may cause large objects
to be allocated dynamically . */
int flag_stack_check ;
2002-02-06 04:59:39 +00:00
/* When non-NULL, indicates that whenever space is allocated on the
stack , the resulting stack pointer must not pass this
address - - - that is , for stacks that grow downward , the stack pointer
must always be greater than or equal to this address ; for stacks
that grow upward , the stack pointer must be less than this address .
At present , the rtx may be either a REG or a SYMBOL_REF , although
the support provided depends on the backend . */
rtx stack_limit_rtx ;
1999-08-30 04:01:02 +00:00
/* 0 if pointer arguments may alias each other. True in C.
1 if pointer arguments may not alias each other but may alias
global variables .
2 if pointer arguments may not alias each other and may not
alias global variables . True in Fortran .
This defaults to 0 for C . */
int flag_argument_noalias = 0 ;
/* Nonzero if we should do (language-dependent) alias analysis.
Typically , this analysis will assume that expressions of certain
types do not alias expressions of certain other types . Only used
if alias analysis ( in general ) is enabled . */
int flag_strict_aliasing = 0 ;
1999-10-27 09:31:52 +00:00
/* Instrument functions with calls at entry and exit, for profiling. */
int flag_instrument_function_entry_exit = 0 ;
/* Nonzero means ignore `#ident' directives. 0 means handle them.
On SVR4 targets , it also controls whether or not to emit a
string identifying the compiler . */
1999-08-30 04:01:02 +00:00
1999-10-27 09:31:52 +00:00
int flag_no_ident = 0 ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* This will perform a peephole pass before sched2. */
int flag_peephole2 = 0 ;
/* This will try to guess branch probabilities. */
int flag_guess_branch_prob = 0 ;
/* -fbounded-pointers causes gcc to compile pointers as composite
objects occupying three words : the pointer value , the base address
of the referent object , and the address immediately beyond the end
of the referent object . The base and extent allow us to perform
runtime bounds checking . - fbounded - pointers implies - fcheck - bounds . */
int flag_bounded_pointers = 0 ;
/* -fcheck-bounds causes gcc to generate array bounds checks.
For C , C + + : defaults to value of flag_bounded_pointers .
For ObjC : defaults to off .
For Java : defaults to on .
For Fortran : defaults to off .
For CHILL : defaults to off . */
int flag_bounds_check = 0 ;
/* This will attempt to merge constant section constants, if 1 only
string constants and constants from constant pool , if 2 also constant
variables . */
int flag_merge_constants = 1 ;
/* If one, renumber instruction UIDs to reduce the number of
unused UIDs if there are a lot of instructions . If greater than
one , unconditionally renumber instruction UIDs . */
int flag_renumber_insns = 1 ;
/* Values of the -falign-* flags: how much to align labels in code.
0 means ` use default ' , 1 means ` don ' t align ' .
For each variable , there is an _log variant which is the power
of two not less than the variable , for . align output . */
int align_loops ;
int align_loops_log ;
int align_loops_max_skip ;
int align_jumps ;
int align_jumps_log ;
int align_jumps_max_skip ;
int align_labels ;
int align_labels_log ;
int align_labels_max_skip ;
int align_functions ;
int align_functions_log ;
2002-10-10 04:51:11 +00:00
/* Like align_functions_log above, but used by front-ends to force the
minimum function alignment . Zero means no alignment is forced . */
int force_align_functions_log ;
1999-08-30 04:01:02 +00:00
/* Table of supported debugging formats. */
2002-02-06 04:59:39 +00:00
static const struct
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
const char * const arg ;
1999-08-30 04:01:02 +00:00
/* Since PREFERRED_DEBUGGING_TYPE isn't necessarily a
constant expression , we use NO_DEBUG in its place . */
2002-02-06 04:59:39 +00:00
const enum debug_info_type debug_type ;
const int use_extensions_p ;
const char * const description ;
1999-08-30 04:01:02 +00:00
} * da ,
debug_args [ ] =
{
2002-02-06 04:59:39 +00:00
{ " " , NO_DEBUG , DEFAULT_GDB_EXTENSIONS ,
N_ ( " Generate debugging info in default format " ) } ,
{ " gdb " , NO_DEBUG , 1 , N_ ( " Generate debugging info in default extended format " ) } ,
1999-08-30 04:01:02 +00:00
# ifdef DBX_DEBUGGING_INFO
2002-02-06 04:59:39 +00:00
{ " stabs " , DBX_DEBUG , 0 , N_ ( " Generate STABS format debug info " ) } ,
{ " stabs+ " , DBX_DEBUG , 1 , N_ ( " Generate extended STABS format debug info " ) } ,
1999-08-30 04:01:02 +00:00
# endif
# ifdef DWARF_DEBUGGING_INFO
2002-02-06 04:59:39 +00:00
{ " dwarf " , DWARF_DEBUG , 0 , N_ ( " Generate DWARF-1 format debug info " ) } ,
{ " dwarf+ " , DWARF_DEBUG , 1 ,
N_ ( " Generate extended DWARF-1 format debug info " ) } ,
1999-08-30 04:01:02 +00:00
# endif
# ifdef DWARF2_DEBUGGING_INFO
2002-02-06 04:59:39 +00:00
{ " dwarf-2 " , DWARF2_DEBUG , 0 , N_ ( " Generate DWARF-2 debug info " ) } ,
1999-08-30 04:01:02 +00:00
# endif
# ifdef XCOFF_DEBUGGING_INFO
2002-02-06 04:59:39 +00:00
{ " xcoff " , XCOFF_DEBUG , 0 , N_ ( " Generate XCOFF format debug info " ) } ,
{ " xcoff+ " , XCOFF_DEBUG , 1 , N_ ( " Generate extended XCOFF format debug info " ) } ,
1999-08-30 04:01:02 +00:00
# endif
# ifdef SDB_DEBUGGING_INFO
2002-02-06 04:59:39 +00:00
{ " coff " , SDB_DEBUG , 0 , N_ ( " Generate COFF format debug info " ) } ,
2002-05-09 22:15:04 +00:00
# endif
# ifdef VMS_DEBUGGING_INFO
{ " vms " , VMS_DEBUG , 0 , N_ ( " Generate VMS format debug info " ) } ,
1999-08-30 04:01:02 +00:00
# endif
1999-10-27 09:31:52 +00:00
{ 0 , 0 , 0 , 0 }
1999-08-30 04:01:02 +00:00
} ;
typedef struct
{
2002-02-06 04:59:39 +00:00
const char * const string ;
int * const variable ;
const int on_value ;
const char * const description ;
1999-08-30 04:01:02 +00:00
}
lang_independent_options ;
2002-02-06 04:59:39 +00:00
int flag_trapv = 0 ;
1999-10-27 09:31:52 +00:00
/* Add or remove a leading underscore from user symbols. */
int flag_leading_underscore = - 1 ;
/* The user symbol prefix after having resolved same. */
const char * user_label_prefix ;
2002-02-06 04:59:39 +00:00
static const param_info lang_independent_params [ ] = {
# define DEFPARAM(ENUM, OPTION, HELP, DEFAULT) \
{ OPTION , DEFAULT , HELP } ,
# include "params.def"
# undef DEFPARAM
{ NULL , 0 , NULL }
} ;
1999-10-27 09:31:52 +00:00
/* A default for same. */
# ifndef USER_LABEL_PREFIX
# define USER_LABEL_PREFIX ""
# endif
1996-09-18 05:35:50 +00:00
/* Table of language-independent -f options.
STRING is the option name . VARIABLE is the address of the variable .
ON_VALUE is the value to store in VARIABLE
if ` - fSTRING ' is seen as an option .
( If ` - fno - STRING ' is seen as an option , the opposite value is stored . ) */
2002-02-06 04:59:39 +00:00
static const lang_independent_options f_options [ ] =
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
{ " format-extensions " , & flag_format_extensions , 1 ,
N_ ( " -Wformat accepts certain FreeBSD system-dependent formats " ) } ,
{ " eliminate-dwarf2-dups " , & flag_eliminate_dwarf2_dups , 1 ,
N_ ( " Perform DWARF2 duplicate elimination " ) } ,
1999-08-30 04:01:02 +00:00
{ " float-store " , & flag_float_store , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Do not store floats in registers " ) } ,
1999-08-30 04:01:02 +00:00
{ " volatile " , & flag_volatile , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Consider all mem refs through pointers as volatile " ) } ,
1999-08-30 04:01:02 +00:00
{ " volatile-global " , & flag_volatile_global , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Consider all mem refs to global data to be volatile " ) } ,
1999-10-27 09:31:52 +00:00
{ " volatile-static " , & flag_volatile_static , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Consider all mem refs to static data to be volatile " ) } ,
1999-08-30 04:01:02 +00:00
{ " defer-pop " , & flag_defer_pop , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Defer popping functions args from stack until later " ) } ,
1999-08-30 04:01:02 +00:00
{ " omit-frame-pointer " , & flag_omit_frame_pointer , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " When possible do not generate stack frames " ) } ,
{ " optimize-sibling-calls " , & flag_optimize_sibling_calls , 1 ,
N_ ( " Optimize sibling and tail recursive calls " ) } ,
1999-08-30 04:01:02 +00:00
{ " cse-follow-jumps " , & flag_cse_follow_jumps , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " When running CSE, follow jumps to their targets " ) } ,
1999-08-30 04:01:02 +00:00
{ " cse-skip-blocks " , & flag_cse_skip_blocks , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " When running CSE, follow conditional jumps " ) } ,
1999-08-30 04:01:02 +00:00
{ " expensive-optimizations " , & flag_expensive_optimizations , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Perform a number of minor, expensive optimizations " ) } ,
1999-08-30 04:01:02 +00:00
{ " thread-jumps " , & flag_thread_jumps , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Perform jump threading optimizations " ) } ,
1999-08-30 04:01:02 +00:00
{ " strength-reduce " , & flag_strength_reduce , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Perform strength reduction optimizations " ) } ,
1999-08-30 04:01:02 +00:00
{ " unroll-loops " , & flag_unroll_loops , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Perform loop unrolling when iteration count is known " ) } ,
1999-08-30 04:01:02 +00:00
{ " unroll-all-loops " , & flag_unroll_all_loops , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Perform loop unrolling for all loops " ) } ,
{ " prefetch-loop-arrays " , & flag_prefetch_loop_arrays , 1 ,
N_ ( " Generate prefetch instructions, if available, for arrays in loops " ) } ,
1999-08-30 04:01:02 +00:00
{ " move-all-movables " , & flag_move_all_movables , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Force all loop invariant computations out of loops " ) } ,
1999-08-30 04:01:02 +00:00
{ " reduce-all-givs " , & flag_reduce_all_givs , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Strength reduce all loop general induction variables " ) } ,
1999-08-30 04:01:02 +00:00
{ " writable-strings " , & flag_writable_strings , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Store strings in writable data section " ) } ,
1999-08-30 04:01:02 +00:00
{ " peephole " , & flag_no_peephole , 0 ,
2002-02-06 04:59:39 +00:00
N_ ( " Enable machine specific peephole optimizations " ) } ,
1999-08-30 04:01:02 +00:00
{ " force-mem " , & flag_force_mem , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Copy memory operands into registers before using " ) } ,
1999-08-30 04:01:02 +00:00
{ " force-addr " , & flag_force_addr , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Copy memory address constants into regs before using " ) } ,
1999-08-30 04:01:02 +00:00
{ " function-cse " , & flag_no_function_cse , 0 ,
2002-02-06 04:59:39 +00:00
N_ ( " Allow function addresses to be held in registers " ) } ,
1999-08-30 04:01:02 +00:00
{ " inline-functions " , & flag_inline_functions , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Integrate simple functions into their callers " ) } ,
1999-08-30 04:01:02 +00:00
{ " keep-inline-functions " , & flag_keep_inline_functions , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Generate code for funcs even if they are fully inlined " ) } ,
1999-08-30 04:01:02 +00:00
{ " inline " , & flag_no_inline , 0 ,
2002-02-06 04:59:39 +00:00
N_ ( " Pay attention to the 'inline' keyword " ) } ,
1999-08-30 04:01:02 +00:00
{ " keep-static-consts " , & flag_keep_static_consts , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Emit static const variables even if they are not used " ) } ,
1999-08-30 04:01:02 +00:00
{ " syntax-only " , & flag_syntax_only , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Check for syntax errors, then stop " ) } ,
1999-08-30 04:01:02 +00:00
{ " shared-data " , & flag_shared_data , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Mark data as shared rather than private " ) } ,
1999-08-30 04:01:02 +00:00
{ " caller-saves " , & flag_caller_saves , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Enable saving registers around function calls " ) } ,
1999-08-30 04:01:02 +00:00
{ " pcc-struct-return " , & flag_pcc_struct_return , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Return 'short' aggregates in memory, not registers " ) } ,
1999-08-30 04:01:02 +00:00
{ " reg-struct-return " , & flag_pcc_struct_return , 0 ,
2002-02-06 04:59:39 +00:00
N_ ( " Return 'short' aggregates in registers " ) } ,
1999-08-30 04:01:02 +00:00
{ " delayed-branch " , & flag_delayed_branch , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Attempt to fill delay slots of branch instructions " ) } ,
1999-08-30 04:01:02 +00:00
{ " gcse " , & flag_gcse , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Perform the global common subexpression elimination " ) } ,
{ " gcse-lm " , & flag_gcse_lm , 1 ,
N_ ( " Perform enhanced load motion during global subexpression elimination " ) } ,
{ " gcse-sm " , & flag_gcse_sm , 1 ,
N_ ( " Perform store motion after global subexpression elimination " ) } ,
1999-08-30 04:01:02 +00:00
{ " rerun-cse-after-loop " , & flag_rerun_cse_after_loop , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Run CSE pass after loop optimizations " ) } ,
1999-08-30 04:01:02 +00:00
{ " rerun-loop-opt " , & flag_rerun_loop_opt , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Run the loop optimizer twice " ) } ,
{ " delete-null-pointer-checks " , & flag_delete_null_pointer_checks , 1 ,
N_ ( " Delete useless null pointer checks " ) } ,
1999-08-30 04:01:02 +00:00
{ " pretend-float " , & flag_pretend_float , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Pretend that host and target use the same FP format " ) } ,
1999-08-30 04:01:02 +00:00
{ " schedule-insns " , & flag_schedule_insns , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Reschedule instructions before register allocation " ) } ,
1999-08-30 04:01:02 +00:00
{ " schedule-insns2 " , & flag_schedule_insns_after_reload , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Reschedule instructions after register allocation " ) } ,
1999-08-30 04:01:02 +00:00
{ " sched-interblock " , & flag_schedule_interblock , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Enable scheduling across basic blocks " ) } ,
1999-08-30 04:01:02 +00:00
{ " sched-spec " , & flag_schedule_speculative , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Allow speculative motion of non-loads " ) } ,
1999-08-30 04:01:02 +00:00
{ " sched-spec-load " , & flag_schedule_speculative_load , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Allow speculative motion of some loads " ) } ,
1999-08-30 04:01:02 +00:00
{ " sched-spec-load-dangerous " , & flag_schedule_speculative_load_dangerous , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Allow speculative motion of more loads " ) } ,
1999-08-30 04:01:02 +00:00
{ " branch-count-reg " , & flag_branch_on_count_reg , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Replace add,compare,branch with branch on count reg " ) } ,
1999-08-30 04:01:02 +00:00
{ " pic " , & flag_pic , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Generate position independent code, if possible " ) } ,
1999-08-30 04:01:02 +00:00
{ " PIC " , & flag_pic , 2 , " " } ,
{ " exceptions " , & flag_exceptions , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Enable exception handling " ) } ,
{ " unwind-tables " , & flag_unwind_tables , 1 ,
N_ ( " Just generate unwind tables for exception handling " ) } ,
{ " asynchronous-unwind-tables " , & flag_asynchronous_unwind_tables , 1 ,
N_ ( " Generate unwind tables exact at each instruction boundary " ) } ,
{ " non-call-exceptions " , & flag_non_call_exceptions , 1 ,
N_ ( " Support synchronous non-call exceptions " ) } ,
1999-08-30 04:01:02 +00:00
{ " profile-arcs " , & profile_arc_flag , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Insert arc based program profiling code " ) } ,
1999-08-30 04:01:02 +00:00
{ " test-coverage " , & flag_test_coverage , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Create data files needed by gcov " ) } ,
1999-08-30 04:01:02 +00:00
{ " branch-probabilities " , & flag_branch_probabilities , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Use profiling information for branch probabilities " ) } ,
{ " reorder-blocks " , & flag_reorder_blocks , 1 ,
N_ ( " Reorder basic blocks to improve code placement " ) } ,
{ " rename-registers " , & flag_rename_registers , 1 ,
N_ ( " Do the register renaming optimization pass " ) } ,
{ " cprop-registers " , & flag_cprop_registers , 1 ,
N_ ( " Do the register copy-propagation optimization pass " ) } ,
1999-08-30 04:01:02 +00:00
{ " common " , & flag_no_common , 0 ,
2002-02-06 04:59:39 +00:00
N_ ( " Do not put uninitialized globals in the common section " ) } ,
1999-08-30 04:01:02 +00:00
{ " inhibit-size-directive " , & flag_inhibit_size_directive , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Do not generate .size directives " ) } ,
1999-08-30 04:01:02 +00:00
{ " function-sections " , & flag_function_sections , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " place each function into its own section " ) } ,
1999-10-27 09:31:52 +00:00
{ " data-sections " , & flag_data_sections , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " place data items into their own section " ) } ,
1999-08-30 04:01:02 +00:00
{ " verbose-asm " , & flag_verbose_asm , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Add extra commentry to assembler output " ) } ,
1999-08-30 04:01:02 +00:00
{ " gnu-linker " , & flag_gnu_linker , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Output GNU ld formatted global initializers " ) } ,
1999-08-30 04:01:02 +00:00
{ " regmove " , & flag_regmove , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Enables a register move optimization " ) } ,
1999-10-27 09:31:52 +00:00
{ " optimize-register-move " , & flag_regmove , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Do the full regmove optimization pass " ) } ,
1999-08-30 04:01:02 +00:00
{ " pack-struct " , & flag_pack_struct , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Pack structure members together without holes " ) } ,
1999-08-30 04:01:02 +00:00
{ " stack-check " , & flag_stack_check , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Insert stack checking code into the program " ) } ,
1999-08-30 04:01:02 +00:00
{ " argument-alias " , & flag_argument_noalias , 0 ,
2002-02-06 04:59:39 +00:00
N_ ( " Specify that arguments may alias each other & globals " ) } ,
1999-08-30 04:01:02 +00:00
{ " argument-noalias " , & flag_argument_noalias , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Assume arguments may alias globals but not each other " ) } ,
1999-08-30 04:01:02 +00:00
{ " argument-noalias-global " , & flag_argument_noalias , 2 ,
2002-02-06 04:59:39 +00:00
N_ ( " Assume arguments do not alias each other or globals " ) } ,
1999-08-30 04:01:02 +00:00
{ " strict-aliasing " , & flag_strict_aliasing , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Assume strict aliasing rules apply " ) } ,
{ " align-loops " , & align_loops , 0 ,
N_ ( " Align the start of loops " ) } ,
{ " align-jumps " , & align_jumps , 0 ,
N_ ( " Align labels which are only reached by jumping " ) } ,
{ " align-labels " , & align_labels , 0 ,
N_ ( " Align all labels " ) } ,
{ " align-functions " , & align_functions , 0 ,
N_ ( " Align the start of functions " ) } ,
{ " merge-constants " , & flag_merge_constants , 1 ,
N_ ( " Attempt to merge identical constants accross compilation units " ) } ,
{ " merge-all-constants " , & flag_merge_constants , 2 ,
N_ ( " Attempt to merge identical constants and constant variables " ) } ,
1999-10-27 09:31:52 +00:00
{ " dump-unnumbered " , & flag_dump_unnumbered , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Suppress output of instruction numbers and line number notes in debugging dumps " ) } ,
1999-10-27 09:31:52 +00:00
{ " instrument-functions " , & flag_instrument_function_entry_exit , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Instrument function entry/exit with profiling calls " ) } ,
{ " ssa " , & flag_ssa , 1 ,
N_ ( " Enable SSA optimizations " ) } ,
{ " ssa-ccp " , & flag_ssa_ccp , 1 ,
N_ ( " Enable SSA conditional constant propagation " ) } ,
{ " ssa-dce " , & flag_ssa_dce , 1 ,
N_ ( " Enable aggressive SSA dead code elimination " ) } ,
1999-10-27 09:31:52 +00:00
{ " leading-underscore " , & flag_leading_underscore , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " External symbols have a leading underscore " ) } ,
1999-10-27 09:31:52 +00:00
{ " ident " , & flag_no_ident , 0 ,
2002-02-06 04:59:39 +00:00
N_ ( " Process #ident directives " ) } ,
{ " peephole2 " , & flag_peephole2 , 1 ,
N_ ( " Enables an rtl peephole pass run before sched2 " ) } ,
{ " guess-branch-probability " , & flag_guess_branch_prob , 1 ,
N_ ( " Enables guessing of branch probabilities " ) } ,
{ " math-errno " , & flag_errno_math , 1 ,
N_ ( " Set errno after built-in math functions " ) } ,
{ " trapping-math " , & flag_trapping_math , 1 ,
N_ ( " Floating-point operations can trap " ) } ,
{ " unsafe-math-optimizations " , & flag_unsafe_math_optimizations , 1 ,
N_ ( " Allow math optimizations that may violate IEEE or ANSI standards " ) } ,
{ " bounded-pointers " , & flag_bounded_pointers , 1 ,
N_ ( " Compile pointers as triples: value, base & end " ) } ,
{ " bounds-check " , & flag_bounds_check , 1 ,
N_ ( " Generate code to check bounds before dereferencing pointers and arrays " ) } ,
{ " single-precision-constant " , & flag_single_precision_constant , 1 ,
N_ ( " Convert floating point constant to single precision constant " ) } ,
{ " time-report " , & time_report , 1 ,
N_ ( " Report time taken by each compiler pass at end of run " ) } ,
{ " mem-report " , & mem_report , 1 ,
N_ ( " Report on permanent memory allocation at end of run " ) } ,
{ " trapv " , & flag_trapv , 1 ,
N_ ( " Trap for signed overflow in addition / subtraction / multiplication " ) } ,
1996-09-18 05:35:50 +00:00
} ;
/* Table of language-specific options. */
2002-02-06 04:59:39 +00:00
static const struct lang_opt
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
const char * const option ;
const char * const description ;
1999-08-30 04:01:02 +00:00
}
documented_lang_options [ ] =
{
/* In order not to overload the --help output, the convention
used here is to only describe those options which are not
enabled by default . */
2002-02-06 04:59:39 +00:00
{ " -ansi " ,
N_ ( " Compile just for ISO C89 " ) } ,
1999-08-30 04:01:02 +00:00
{ " -fallow-single-precision " ,
2002-02-06 04:59:39 +00:00
N_ ( " Do not promote floats to double if using -traditional " ) } ,
{ " -std= " ,
N_ ( " Determine language standard " ) } ,
1999-08-30 04:01:02 +00:00
{ " -fsigned-bitfields " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -funsigned-bitfields " ,
N_ ( " Make bit-fields by unsigned by default " ) } ,
1999-08-30 04:01:02 +00:00
{ " -fno-signed-bitfields " , " " } ,
{ " -fno-unsigned-bitfields " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -fsigned-char " ,
N_ ( " Make 'char' be signed by default " ) } ,
{ " -funsigned-char " ,
N_ ( " Make 'char' be unsigned by default " ) } ,
1999-08-30 04:01:02 +00:00
{ " -fno-signed-char " , " " } ,
{ " -fno-unsigned-char " , " " } ,
{ " -ftraditional " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -traditional " ,
N_ ( " Attempt to support traditional K&R style C " ) } ,
1999-08-30 04:01:02 +00:00
{ " -fnotraditional " , " " } ,
{ " -fno-traditional " , " " } ,
{ " -fasm " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -fno-asm " ,
N_ ( " Do not recognize the 'asm' keyword " ) } ,
1999-08-30 04:01:02 +00:00
{ " -fbuiltin " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -fno-builtin " ,
N_ ( " Do not recognize any built in functions " ) } ,
{ " -fhosted " ,
N_ ( " Assume normal C execution environment " ) } ,
1999-08-30 04:01:02 +00:00
{ " -fno-hosted " , " " } ,
{ " -ffreestanding " ,
2002-02-06 04:59:39 +00:00
N_ ( " Assume that standard libraries & main might not exist " ) } ,
1999-08-30 04:01:02 +00:00
{ " -fno-freestanding " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -fcond-mismatch " ,
N_ ( " Allow different types as args of ? operator " ) } ,
1999-08-30 04:01:02 +00:00
{ " -fno-cond-mismatch " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -fdollars-in-identifiers " ,
N_ ( " Allow the use of $ inside identifiers " ) } ,
1999-08-30 04:01:02 +00:00
{ " -fno-dollars-in-identifiers " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -fpreprocessed " , " " } ,
{ " -fno-preprocessed " , " " } ,
{ " -fshort-double " ,
N_ ( " Use the same size for double as for float " ) } ,
1999-08-30 04:01:02 +00:00
{ " -fno-short-double " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -fshort-enums " ,
N_ ( " Use the smallest fitting integer to hold enums " ) } ,
1999-08-30 04:01:02 +00:00
{ " -fno-short-enums " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -fshort-wchar " ,
N_ ( " Override the underlying type for wchar_t to `unsigned short' " ) } ,
{ " -fno-short-wchar " , " " } ,
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
{ " -Wall " ,
N_ ( " Enable most warning messages " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wbad-function-cast " ,
2002-02-06 04:59:39 +00:00
N_ ( " Warn about casting functions to incompatible types " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-bad-function-cast " , " " } ,
1999-10-27 09:31:52 +00:00
{ " -Wno-missing-noreturn " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wmissing-format-attribute " ,
N_ ( " Warn about functions which might be candidates for format attributes " ) } ,
{ " -Wno-missing-format-attribute " , " " } ,
{ " -Wcast-qual " ,
N_ ( " Warn about casts which discard qualifiers " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-cast-qual " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wchar-subscripts " ,
N_ ( " Warn about subscripts whose type is 'char' " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-char-subscripts " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wcomment " ,
N_ ( " Warn if nested comments are detected " ) } ,
1999-10-27 09:31:52 +00:00
{ " -Wno-comment " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wcomments " ,
N_ ( " Warn if nested comments are detected " ) } ,
1999-10-27 09:31:52 +00:00
{ " -Wno-comments " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wconversion " ,
N_ ( " Warn about possibly confusing type conversions " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-conversion " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wformat " ,
N_ ( " Warn about printf/scanf/strftime/strfmon format anomalies " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-format " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wformat-y2k " , " " } ,
{ " -Wno-format-y2k " ,
N_ ( " Don't warn about strftime formats yielding 2 digit years " ) } ,
{ " -Wformat-extra-args " , " " } ,
{ " -Wno-format-extra-args " ,
N_ ( " Don't warn about too many arguments to format functions " ) } ,
{ " -Wformat-nonliteral " ,
N_ ( " Warn about non-string-literal format strings " ) } ,
{ " -Wno-format-nonliteral " , " " } ,
{ " -Wformat-security " ,
N_ ( " Warn about possible security problems with format functions " ) } ,
{ " -Wno-format-security " , " " } ,
1999-08-30 04:01:02 +00:00
{ " -Wimplicit-function-declaration " ,
2002-02-06 04:59:39 +00:00
N_ ( " Warn about implicit function declarations " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-implicit-function-declaration " , " " } ,
{ " -Werror-implicit-function-declaration " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wimplicit-int " ,
N_ ( " Warn when a declaration does not specify a type " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-implicit-int " , " " } ,
{ " -Wimplicit " , " " } ,
{ " -Wno-implicit " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wimport " ,
N_ ( " Warn about the use of the #import directive " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-import " , " " } ,
{ " -Wlong-long " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wno-long-long " ,
N_ ( " Do not warn about using 'long long' when -pedantic " ) } ,
{ " -Wmain " ,
N_ ( " Warn about suspicious declarations of main " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-main " , " " } ,
{ " -Wmissing-braces " ,
2002-02-06 04:59:39 +00:00
N_ ( " Warn about possibly missing braces around initializers " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-missing-braces " , " " } ,
{ " -Wmissing-declarations " ,
2002-02-06 04:59:39 +00:00
N_ ( " Warn about global funcs without previous declarations " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-missing-declarations " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wmissing-prototypes " ,
N_ ( " Warn about global funcs without prototypes " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-missing-prototypes " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wmultichar " ,
N_ ( " Warn about use of multicharacter literals " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-multichar " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wnested-externs " ,
N_ ( " Warn about externs not at file scope level " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-nested-externs " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wparentheses " ,
N_ ( " Warn about possible missing parentheses " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-parentheses " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wsequence-point " ,
N_ ( " Warn about possible violations of sequence point rules " ) } ,
{ " -Wno-sequence-point " , " " } ,
{ " -Wpointer-arith " ,
N_ ( " Warn about function pointer arithmetic " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-pointer-arith " , " " } ,
{ " -Wredundant-decls " ,
2002-02-06 04:59:39 +00:00
N_ ( " Warn about multiple declarations of the same object " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-redundant-decls " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wsign-compare " ,
N_ ( " Warn about signed/unsigned comparisons " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-sign-compare " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wfloat-equal " ,
N_ ( " Warn about testing equality of floating point numbers " ) } ,
{ " -Wno-float-equal " , " " } ,
{ " -Wunknown-pragmas " ,
N_ ( " Warn about unrecognized pragmas " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-unknown-pragmas " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wstrict-prototypes " ,
N_ ( " Warn about non-prototyped function decls " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-strict-prototypes " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wtraditional " ,
N_ ( " Warn about constructs whose meaning change in ISO C " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-traditional " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wtrigraphs " ,
N_ ( " Warn when trigraphs are encountered " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-trigraphs " , " " } ,
{ " -Wundef " , " " } ,
{ " -Wno-undef " , " " } ,
2002-02-06 04:59:39 +00:00
{ " -Wwrite-strings " ,
N_ ( " Mark strings as 'const char *' " ) } ,
1999-08-30 04:01:02 +00:00
{ " -Wno-write-strings " , " " } ,
# define DEFINE_LANG_NAME(NAME) { NULL, NAME },
1996-09-18 05:35:50 +00:00
# include "options.h"
2002-02-06 04:59:39 +00:00
1996-09-18 05:35:50 +00:00
} ;
1999-08-30 04:01:02 +00:00
/* Here is a table, controlled by the tm.h file, listing each -m switch
and which bits in ` target_switches ' it should set or clear .
If VALUE is positive , it is bits to set .
If VALUE is negative , - VALUE is bits to clear .
( The sign bit is not used so there is no confusion . ) */
2002-02-06 04:59:39 +00:00
static const struct
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
const char * const name ;
const int value ;
const char * const description ;
1999-08-30 04:01:02 +00:00
}
target_switches [ ] = TARGET_SWITCHES ;
/* This table is similar, but allows the switch to have a value. */
# ifdef TARGET_OPTIONS
2002-02-06 04:59:39 +00:00
static const struct
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
const char * const prefix ;
const char * * const variable ;
const char * const description ;
1999-08-30 04:01:02 +00:00
}
target_options [ ] = TARGET_OPTIONS ;
# endif
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Options controlling warnings. */
1996-09-18 05:35:50 +00:00
/* Don't print warning messages. -w. */
int inhibit_warnings = 0 ;
2002-02-06 04:59:39 +00:00
/* Don't suppress warnings from system headers. -Wsystem-headers. */
int warn_system_headers = 0 ;
1996-09-18 05:35:50 +00:00
/* Print various extra warnings. -W. */
int extra_warnings = 0 ;
/* Treat warnings as errors. -Werror. */
int warnings_are_errors = 0 ;
2002-02-06 04:59:39 +00:00
/* Nonzero to warn about unused variables, functions et.al. */
int warn_unused_function ;
int warn_unused_label ;
int warn_unused_parameter ;
int warn_unused_variable ;
int warn_unused_value ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Nonzero to warn about code which is never reached. */
int warn_notreached ;
1996-09-18 05:35:50 +00:00
/* Nonzero to warn about variables used before they are initialized. */
int warn_uninitialized ;
2002-02-06 04:59:39 +00:00
/* Nonzero means warn about all declarations which shadow others. */
1996-09-18 05:35:50 +00:00
int warn_shadow ;
/* Warn if a switch on an enum fails to have a case for every enum value. */
int warn_switch ;
/* Nonzero means warn about function definitions that default the return type
or that use a null return and have a return - type other than void . */
int warn_return_type ;
/* Nonzero means warn about pointer casts that increase the required
alignment of the target type ( and might therefore lead to a crash
due to a misaligned access ) . */
int warn_cast_align ;
/* Nonzero means warn about any objects definitions whose size is larger
than N bytes . Also want about function definitions whose returned
values are larger than N bytes . The value N is in ` larger_than_size ' . */
2002-02-06 04:59:39 +00:00
1996-09-18 05:35:50 +00:00
int warn_larger_than ;
2002-02-06 04:59:39 +00:00
HOST_WIDE_INT larger_than_size ;
1996-09-18 05:35:50 +00:00
/* Nonzero means warn if inline function is too large. */
int warn_inline ;
/* Warn if a function returns an aggregate,
since there are often incompatible calling conventions for doing this . */
int warn_aggregate_return ;
2002-02-06 04:59:39 +00:00
/* Warn if packed attribute on struct is unnecessary and inefficient. */
int warn_packed ;
/* Warn when gcc pads a structure to an alignment boundary. */
int warn_padded ;
/* Warn when an optimization pass is disabled. */
int warn_disabled_optimization ;
/* Warn about functions which might be candidates for attribute noreturn. */
int warn_missing_noreturn ;
/* Nonzero means warn about uses of __attribute__((deprecated))
declarations . */
int warn_deprecated_decl = 1 ;
1996-09-18 05:35:50 +00:00
/* Likewise for -W. */
2002-02-06 04:59:39 +00:00
static const lang_independent_options W_options [ ] =
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
{ " unused-function " , & warn_unused_function , 1 ,
N_ ( " Warn when a function is unused " ) } ,
{ " unused-label " , & warn_unused_label , 1 ,
N_ ( " Warn when a label is unused " ) } ,
{ " unused-parameter " , & warn_unused_parameter , 1 ,
N_ ( " Warn when a function parameter is unused " ) } ,
{ " unused-variable " , & warn_unused_variable , 1 ,
N_ ( " Warn when a variable is unused " ) } ,
{ " unused-value " , & warn_unused_value , 1 ,
N_ ( " Warn when an expression value is unused " ) } ,
{ " system-headers " , & warn_system_headers , 1 ,
N_ ( " Do not suppress warnings from system headers " ) } ,
{ " error " , & warnings_are_errors , 1 ,
N_ ( " Treat all warnings as errors " ) } ,
{ " shadow " , & warn_shadow , 1 ,
N_ ( " Warn when one local variable shadows another " ) } ,
1999-08-30 04:01:02 +00:00
{ " switch " , & warn_switch , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Warn about enumerated switches missing a specific case " ) } ,
1999-08-30 04:01:02 +00:00
{ " aggregate-return " , & warn_aggregate_return , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Warn about returning structures, unions or arrays " ) } ,
1999-08-30 04:01:02 +00:00
{ " cast-align " , & warn_cast_align , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Warn about pointer casts which increase alignment " ) } ,
{ " unreachable-code " , & warn_notreached , 1 ,
N_ ( " Warn about code that will never be executed " ) } ,
1999-08-30 04:01:02 +00:00
{ " uninitialized " , & warn_uninitialized , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Warn about uninitialized automatic variables " ) } ,
1999-08-30 04:01:02 +00:00
{ " inline " , & warn_inline , 1 ,
2002-02-06 04:59:39 +00:00
N_ ( " Warn when an inlined function cannot be inlined " ) } ,
{ " packed " , & warn_packed , 1 ,
N_ ( " Warn when the packed attribute has no effect on struct layout " ) } ,
{ " padded " , & warn_padded , 1 ,
N_ ( " Warn when padding is required to align struct members " ) } ,
{ " disabled-optimization " , & warn_disabled_optimization , 1 ,
N_ ( " Warn when an optimization pass is disabled " ) } ,
{ " deprecated-declarations " , & warn_deprecated_decl , 1 ,
N_ ( " Warn about uses of __attribute__((deprecated)) declarations " ) } ,
{ " missing-noreturn " , & warn_missing_noreturn , 1 ,
N_ ( " Warn about functions which might be candidates for attribute noreturn " ) }
1996-09-18 05:35:50 +00:00
} ;
2002-02-06 04:59:39 +00:00
void
set_Wunused ( setting )
int setting ;
{
warn_unused_function = setting ;
warn_unused_label = setting ;
/* Unused function parameter warnings are reported when either ``-W
- Wunused ' ' or ` ` - Wunused - parameter ' ' is specified . Differentiate
- Wunused by setting WARN_UNUSED_PARAMETER to - 1. */
if ( ! setting )
warn_unused_parameter = 0 ;
else if ( ! warn_unused_parameter )
warn_unused_parameter = - 1 ;
warn_unused_variable = setting ;
warn_unused_value = setting ;
}
/* The following routines are useful in setting all the flags that
- ffast - math and - fno - fast - math imply . */
void
set_fast_math_flags ( )
{
flag_trapping_math = 0 ;
flag_unsafe_math_optimizations = 1 ;
flag_errno_math = 0 ;
}
void
set_no_fast_math_flags ( )
{
flag_trapping_math = 1 ;
flag_unsafe_math_optimizations = 0 ;
flag_errno_math = 1 ;
}
1996-09-18 05:35:50 +00:00
/* Output files for assembler code (real compiler output)
and debugging dumps . */
FILE * asm_out_file ;
FILE * aux_info_file ;
1999-08-30 04:01:02 +00:00
FILE * rtl_dump_file = NULL ;
1996-09-18 05:35:50 +00:00
1999-10-27 09:31:52 +00:00
/* Decode the string P as an integral parameter.
If the string is indeed an integer return its numeric value else
issue an Invalid Option error for the option PNAME and return DEFVAL .
2002-02-06 04:59:39 +00:00
If PNAME is zero just return DEFVAL , do not call error . */
1999-10-27 09:31:52 +00:00
int
read_integral_parameter ( p , pname , defval )
const char * p ;
const char * pname ;
const int defval ;
{
const char * endp = p ;
while ( * endp )
{
2002-02-06 04:59:39 +00:00
if ( ISDIGIT ( * endp ) )
1999-10-27 09:31:52 +00:00
endp + + ;
else
break ;
}
if ( * endp ! = 0 )
{
if ( pname ! = 0 )
2002-02-06 04:59:39 +00:00
error ( " invalid option `%s' " , pname ) ;
1999-10-27 09:31:52 +00:00
return defval ;
}
return atoi ( p ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* This is the default decl_printable_name function. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
static const char *
decl_name ( decl , verbosity )
tree decl ;
int verbosity ATTRIBUTE_UNUSED ;
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
return IDENTIFIER_POINTER ( DECL_NAME ( decl ) ) ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* This calls abort and is used to avoid problems when abort if a macro.
It is used when we need to pass the address of abort . */
1996-09-18 05:35:50 +00:00
void
2002-02-06 04:59:39 +00:00
do_abort ( )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
abort ( ) ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* When `malloc.c' is compiled with `rcheck' defined,
it calls this function to report clobberage . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
void
botch ( s )
const char * s ATTRIBUTE_UNUSED ;
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
abort ( ) ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Return the logarithm of X, base 2, considering X unsigned,
if X is a power of 2. Otherwise , returns - 1.
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
This should be used via the ` exact_log2 ' macro . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
int
exact_log2_wide ( x )
unsigned HOST_WIDE_INT x ;
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
int log = 0 ;
/* Test for 0 or a power of 2. */
if ( x = = 0 | | x ! = ( x & - x ) )
return - 1 ;
while ( ( x > > = 1 ) ! = 0 )
log + + ;
return log ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
If X is 0 , return - 1.
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
This should be used via the floor_log2 macro . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
int
floor_log2_wide ( x )
unsigned HOST_WIDE_INT x ;
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
int log = - 1 ;
while ( x ! = 0 )
log + + ,
x > > = 1 ;
return log ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
static int float_handler_set ;
int float_handled ;
jmp_buf float_handler ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Signals actually come here. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
static void
float_signal ( signo )
/* If this is missing, some compilers complain. */
int signo ATTRIBUTE_UNUSED ;
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
if ( float_handled = = 0 )
crash_signal ( signo ) ;
float_handled = 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* On System-V derived systems, we must reinstall the signal handler.
This is harmless on BSD - derived systems . */
signal ( SIGFPE , float_signal ) ;
longjmp ( float_handler , 1 ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Specify where to longjmp to when a floating arithmetic error happens.
If HANDLER is 0 , it means don ' t handle the errors any more . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
static void
set_float_handler ( handler )
jmp_buf handler ;
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
float_handled = ( handler ! = 0 ) ;
if ( handler )
memcpy ( float_handler , handler , sizeof ( float_handler ) ) ;
if ( float_handled & & ! float_handler_set )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
signal ( SIGFPE , float_signal ) ;
float_handler_set = 1 ;
1996-09-18 05:35:50 +00:00
}
}
2002-02-06 04:59:39 +00:00
/* This is a wrapper function for code which might elicit an
arithmetic exception . That code should be passed in as a function
pointer FN , and one argument DATA . DATA is usually a struct which
contains the real input and output for function FN . This function
returns 0 ( failure ) if longjmp was called ( i . e . an exception
occurred . ) It returns 1 ( success ) otherwise . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
int
do_float_handler ( fn , data )
void ( * fn ) PARAMS ( ( PTR ) ) ;
PTR data ;
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
jmp_buf buf ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( setjmp ( buf ) )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
/* We got here via longjmp () caused by an exception in function
fn ( ) . */
set_float_handler ( NULL ) ;
return 0 ;
1996-09-18 05:35:50 +00:00
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
set_float_handler ( buf ) ;
( * fn ) ( data ) ;
set_float_handler ( NULL ) ;
return 1 ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Handler for fatal signals, such as SIGSEGV. These are transformed
into ICE messages , which is much more user friendly . */
1996-09-18 05:35:50 +00:00
static void
2002-02-06 04:59:39 +00:00
crash_signal ( signo )
int signo ;
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
internal_error ( " internal error: %s " , strsignal ( signo ) ) ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
/* Strip off a legitimate source ending from the input string NAME of
length LEN . Rather than having to know the names used by all of
our front ends , we strip off an ending of a period followed by
up to five characters . ( Java uses " .class " . ) */
1996-09-18 05:35:50 +00:00
1999-10-27 09:31:52 +00:00
void
2002-02-06 04:59:39 +00:00
strip_off_ending ( name , len )
char * name ;
int len ;
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
int i ;
for ( i = 2 ; i < 6 & & len > i ; i + + )
{
if ( name [ len - i ] = = ' . ' )
{
name [ len - i ] = ' \0 ' ;
break ;
}
}
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
/* Output a quoted string. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
void
output_quoted_string ( asm_file , string )
FILE * asm_file ;
const char * string ;
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
# ifdef OUTPUT_QUOTED_STRING
OUTPUT_QUOTED_STRING ( asm_file , string ) ;
# else
char c ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
putc ( ' \" ' , asm_file ) ;
while ( ( c = * string + + ) ! = 0 )
{
2002-05-09 22:15:04 +00:00
if ( ISPRINT ( c ) )
{
if ( c = = ' \" ' | | c = = ' \\ ' )
putc ( ' \\ ' , asm_file ) ;
putc ( c , asm_file ) ;
}
else
fprintf ( asm_file , " \\ %03o " , c ) ;
2002-02-06 04:59:39 +00:00
}
putc ( ' \" ' , asm_file ) ;
# endif
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
/* Output a file name in the form wanted by System V. */
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
void
output_file_directive ( asm_file , input_name )
FILE * asm_file ;
const char * input_name ;
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
int len = strlen ( input_name ) ;
const char * na = input_name + len ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
/* NA gets INPUT_NAME sans directory names. */
while ( na > input_name )
{
if ( IS_DIR_SEPARATOR ( na [ - 1 ] ) )
break ;
na - - ;
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
# ifdef ASM_OUTPUT_MAIN_SOURCE_FILENAME
ASM_OUTPUT_MAIN_SOURCE_FILENAME ( asm_file , na ) ;
# else
# ifdef ASM_OUTPUT_SOURCE_FILENAME
ASM_OUTPUT_SOURCE_FILENAME ( asm_file , na ) ;
# else
fprintf ( asm_file , " \t .file \t " ) ;
output_quoted_string ( asm_file , na ) ;
fputc ( ' \n ' , asm_file ) ;
# endif
# endif
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Routine to open a dump file. Return true if the dump file is enabled. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
static int
open_dump_file ( index , decl )
enum dump_file_index index ;
1996-09-18 05:35:50 +00:00
tree decl ;
{
2002-02-06 04:59:39 +00:00
char * dump_name ;
const char * open_arg ;
char seq [ 16 ] ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( ! dump_file [ index ] . enabled )
return 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_DUMP ) ;
if ( rtl_dump_file ! = NULL )
fclose ( rtl_dump_file ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
sprintf ( seq , DUMPFILE_FORMAT , index ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( ! dump_file [ index ] . initialized )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
/* If we've not initialized the files, do so now. */
if ( graph_dump_format ! = no_graph
& & dump_file [ index ] . graph_dump_p )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
dump_name = concat ( seq , dump_file [ index ] . extension , NULL ) ;
clean_graph_dump_file ( dump_base_name , dump_name ) ;
free ( dump_name ) ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
dump_file [ index ] . initialized = 1 ;
open_arg = " w " ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
else
open_arg = " a " ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
dump_name = concat ( dump_base_name , seq ,
dump_file [ index ] . extension , NULL ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
rtl_dump_file = fopen ( dump_name , open_arg ) ;
if ( rtl_dump_file = = NULL )
fatal_io_error ( " can't open %s " , dump_name ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
free ( dump_name ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( decl )
fprintf ( rtl_dump_file , " \n ;; Function %s \n \n " ,
decl_printable_name ( decl , 2 ) ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_pop ( TV_DUMP ) ;
return 1 ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Routine to close a dump file. */
1996-09-18 05:35:50 +00:00
static void
2002-02-06 04:59:39 +00:00
close_dump_file ( index , func , insns )
enum dump_file_index index ;
void ( * func ) PARAMS ( ( FILE * , rtx ) ) ;
rtx insns ;
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
if ( ! rtl_dump_file )
return ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_DUMP ) ;
if ( insns
& & graph_dump_format ! = no_graph
& & dump_file [ index ] . graph_dump_p )
{
char seq [ 16 ] ;
char * suffix ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
sprintf ( seq , DUMPFILE_FORMAT , index ) ;
suffix = concat ( seq , dump_file [ index ] . extension , NULL ) ;
print_rtl_graph_with_bb ( dump_base_name , suffix , insns ) ;
free ( suffix ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( func & & insns )
func ( rtl_dump_file , insns ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
fflush ( rtl_dump_file ) ;
fclose ( rtl_dump_file ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
rtl_dump_file = NULL ;
timevar_pop ( TV_DUMP ) ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Do any final processing required for the declarations in VEC, of
which there are LEN . We write out inline functions and variables
that have been deferred until this point , but which are required .
Returns non - zero if anything was put out . */
int
wrapup_global_declarations ( vec , len )
tree * vec ;
int len ;
1996-09-18 05:35:50 +00:00
{
tree decl ;
2002-02-06 04:59:39 +00:00
int i ;
int reconsider ;
int output_something = 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
for ( i = 0 ; i < len ; i + + )
{
decl = vec [ i ] ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* We're not deferring this any longer. */
DECL_DEFER_OUTPUT ( decl ) = 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( TREE_CODE ( decl ) = = VAR_DECL & & DECL_SIZE ( decl ) = = 0
& & incomplete_decl_finalize_hook ! = 0 )
( * incomplete_decl_finalize_hook ) ( decl ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Now emit any global variables or functions that we have been
putting off . We need to loop in case one of the things emitted
here references another one which comes earlier in the list . */
do
{
reconsider = 0 ;
for ( i = 0 ; i < len ; i + + )
{
decl = vec [ i ] ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( TREE_ASM_WRITTEN ( decl ) | | DECL_EXTERNAL ( decl ) )
continue ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Don't write out static consts, unless we still need them.
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
We also keep static consts if not optimizing ( for debugging ) ,
unless the user specified - fno - keep - static - consts .
? ? ? They might be better written into the debug information .
This is possible when using DWARF .
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
A language processor that wants static constants to be always
written out ( even if it is not used ) is responsible for
calling rest_of_decl_compilation itself . E . g . the C front - end
calls rest_of_decl_compilation from finish_decl .
One motivation for this is that is conventional in some
environments to write things like :
static const char rcsid [ ] = " ... version string ... " ;
intending to force the string to be in the executable .
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
A language processor that would prefer to have unneeded
static constants " optimized away " would just defer writing
them out until here . E . g . C + + does this , because static
constants are often defined in header files .
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
? ? ? A tempting alternative ( for both C and C + + ) would be
to force a constant to be written if and only if it is
defined in a main file , as opposed to an include file . */
1996-09-18 05:35:50 +00:00
2002-05-09 22:15:04 +00:00
if ( TREE_CODE ( decl ) = = VAR_DECL & & TREE_STATIC ( decl ) )
2002-02-06 04:59:39 +00:00
{
2002-05-09 22:15:04 +00:00
bool needed = 1 ;
if ( TREE_SYMBOL_REFERENCED ( DECL_ASSEMBLER_NAME ( decl ) ) )
/* needed */ ;
else if ( DECL_COMDAT ( decl ) )
needed = 0 ;
else if ( TREE_READONLY ( decl ) & & ! TREE_PUBLIC ( decl )
& & ( optimize | | ! flag_keep_static_consts
| | DECL_ARTIFICIAL ( decl ) ) )
needed = 0 ;
if ( needed )
{
reconsider = 1 ;
rest_of_decl_compilation ( decl , NULL , 1 , 1 ) ;
}
2002-02-06 04:59:39 +00:00
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( TREE_CODE ( decl ) = = FUNCTION_DECL
& & DECL_INITIAL ( decl ) ! = 0
& & DECL_SAVED_INSNS ( decl ) ! = 0
& & ( flag_keep_inline_functions
| | ( TREE_PUBLIC ( decl ) & & ! DECL_COMDAT ( decl ) )
| | TREE_SYMBOL_REFERENCED ( DECL_ASSEMBLER_NAME ( decl ) ) ) )
{
reconsider = 1 ;
output_inline_function ( decl ) ;
}
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( reconsider )
output_something = 1 ;
}
while ( reconsider ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
return output_something ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Issue appropriate warnings for the global declarations in VEC (of
which there are LEN ) . Output debugging information for them . */
1996-09-18 05:35:50 +00:00
void
2002-02-06 04:59:39 +00:00
check_global_declarations ( vec , len )
tree * vec ;
int len ;
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
tree decl ;
int i ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
for ( i = 0 ; i < len ; i + + )
{
decl = vec [ i ] ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( TREE_CODE ( decl ) = = VAR_DECL & & TREE_STATIC ( decl )
& & ! TREE_ASM_WRITTEN ( decl ) )
/* Cancel the RTL for this decl so that, if debugging info
output for global variables is still to come ,
this one will be omitted . */
SET_DECL_RTL ( decl , NULL_RTX ) ;
/* Warn about any function
declared static but not defined .
We don ' t warn about variables ,
because many programs have static variables
that exist only to get some text into the object file . */
if ( TREE_CODE ( decl ) = = FUNCTION_DECL
& & ( warn_unused_function
| | TREE_SYMBOL_REFERENCED ( DECL_ASSEMBLER_NAME ( decl ) ) )
& & DECL_INITIAL ( decl ) = = 0
& & DECL_EXTERNAL ( decl )
& & ! DECL_ARTIFICIAL ( decl )
& & ! TREE_PUBLIC ( decl ) )
{
if ( TREE_SYMBOL_REFERENCED ( DECL_ASSEMBLER_NAME ( decl ) ) )
pedwarn_with_decl ( decl ,
" `%s' used but never defined " ) ;
else
warning_with_decl ( decl ,
" `%s' declared `static' but never defined " ) ;
/* This symbol is effectively an "extern" declaration now. */
TREE_PUBLIC ( decl ) = 1 ;
assemble_external ( decl ) ;
}
/* Warn about static fns or vars defined but not used,
but not about inline functions or static consts
since defining those in header files is normal practice . */
if ( ( ( warn_unused_function
& & TREE_CODE ( decl ) = = FUNCTION_DECL & & ! DECL_INLINE ( decl ) )
| | ( warn_unused_variable
& & TREE_CODE ( decl ) = = VAR_DECL & & ! TREE_READONLY ( decl ) ) )
& & ! DECL_IN_SYSTEM_HEADER ( decl )
& & ! DECL_EXTERNAL ( decl )
& & ! TREE_PUBLIC ( decl )
& & ! TREE_USED ( decl )
& & ( TREE_CODE ( decl ) = = FUNCTION_DECL | | ! DECL_REGISTER ( decl ) )
/* The TREE_USED bit for file-scope decls
is kept in the identifier , to handle multiple
external decls in different scopes . */
& & ! TREE_USED ( DECL_NAME ( decl ) ) )
warning_with_decl ( decl , " `%s' defined but not used " ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_SYMOUT ) ;
( * debug_hooks - > global_decl ) ( decl ) ;
timevar_pop ( TV_SYMOUT ) ;
}
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Save the current INPUT_FILENAME and LINENO on the top entry in the
INPUT_FILE_STACK . Push a new entry for FILE and LINE , and set the
INPUT_FILENAME and LINENO accordingly . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
void
push_srcloc ( file , line )
1999-10-27 09:31:52 +00:00
const char * file ;
1996-09-18 05:35:50 +00:00
int line ;
{
2002-02-06 04:59:39 +00:00
struct file_stack * fs ;
if ( input_file_stack )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
input_file_stack - > name = input_filename ;
input_file_stack - > line = lineno ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
fs = ( struct file_stack * ) xmalloc ( sizeof ( struct file_stack ) ) ;
fs - > name = input_filename = file ;
fs - > line = lineno = line ;
fs - > indent_level = 0 ;
fs - > next = input_file_stack ;
input_file_stack = fs ;
input_file_stack_tick + + ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Pop the top entry off the stack of presently open source files.
Restore the INPUT_FILENAME and LINENO from the new topmost entry on
the stack . */
1996-09-18 05:35:50 +00:00
void
2002-02-06 04:59:39 +00:00
pop_srcloc ( )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
struct file_stack * fs ;
fs = input_file_stack ;
input_file_stack = fs - > next ;
free ( fs ) ;
input_file_stack_tick + + ;
/* The initial source file is never popped. */
if ( ! input_file_stack )
abort ( ) ;
input_filename = input_file_stack - > name ;
lineno = input_file_stack - > line ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Compile an entire translation unit. Write a file of assembly
output and various debugging dumps . */
1996-09-18 05:35:50 +00:00
static void
2002-02-06 04:59:39 +00:00
compile_file ( )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
tree globals ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Initialize yet another pass. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
init_final ( main_input_filename ) ;
init_branch_prob ( dump_base_name ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_PARSE ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Call the parser, which parses the entire file
( calling rest_of_compilation for each function ) . */
yyparse ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* In case there were missing block closers,
get us back to the global binding level . */
( * lang_hooks . clear_binding_stack ) ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Compilation is now finished except for writing
what ' s left of the symbol table output . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_pop ( TV_PARSE ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( flag_syntax_only )
return ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
globals = getdecls ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Really define vars that have had only a tentative definition.
Really output inline functions that must actually be callable
and have not been output so far . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
{
int len = list_length ( globals ) ;
tree * vec = ( tree * ) xmalloc ( sizeof ( tree ) * len ) ;
int i ;
tree decl ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Process the decls in reverse order--earliest first.
Put them into VEC from back to front , then take out from front . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
for ( i = 0 , decl = globals ; i < len ; i + + , decl = TREE_CHAIN ( decl ) )
vec [ len - i - 1 ] = decl ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
wrapup_global_declarations ( vec , len ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* This must occur after the loop to output deferred functions. Else
the profiler initializer would not be emitted if all the functions
in this compilation unit were deferred .
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
output_func_start_profiler can not cause any additional functions or
data to need to be output , so it need not be in the deferred function
loop above . */
output_func_start_profiler ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
check_global_declarations ( vec , len ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Clean up. */
free ( vec ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Write out any pending weak symbol declarations. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
weak_finish ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Do dbx symbols. */
timevar_push ( TV_SYMOUT ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
# ifdef DWARF2_UNWIND_INFO
if ( dwarf2out_do_frame ( ) )
dwarf2out_frame_finish ( ) ;
1996-09-18 05:35:50 +00:00
# endif
2002-02-06 04:59:39 +00:00
( * debug_hooks - > finish ) ( main_input_filename ) ;
timevar_pop ( TV_SYMOUT ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Output some stuff at end of file if nec. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
dw2_output_indirect_constants ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
end_final ( dump_base_name ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( profile_arc_flag | | flag_test_coverage | | flag_branch_probabilities )
{
timevar_push ( TV_DUMP ) ;
open_dump_file ( DFI_bp , NULL ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
end_branch_prob ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_bp , NULL , NULL_RTX ) ;
timevar_pop ( TV_DUMP ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
# ifdef ASM_FILE_END
ASM_FILE_END ( asm_out_file ) ;
1996-09-18 05:35:50 +00:00
# endif
2002-02-06 04:59:39 +00:00
/* Attach a special .ident directive to the end of the file to identify
the version of GCC which compiled this code . The format of the . ident
string is patterned after the ones produced by native SVR4 compilers . */
# ifdef IDENT_ASM_OP
if ( ! flag_no_ident )
fprintf ( asm_out_file , " %s \" GCC: (GNU) %s \" \n " ,
IDENT_ASM_OP , version_string ) ;
1996-09-18 05:35:50 +00:00
# endif
2002-02-06 04:59:39 +00:00
if ( optimize > 0 & & open_dump_file ( DFI_combine , NULL ) )
{
timevar_push ( TV_DUMP ) ;
dump_combine_total_stats ( rtl_dump_file ) ;
close_dump_file ( DFI_combine , NULL , NULL_RTX ) ;
timevar_pop ( TV_DUMP ) ;
}
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* This is called from various places for FUNCTION_DECL, VAR_DECL,
and TYPE_DECL nodes .
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
This does nothing for local ( non - static ) variables , unless the
variable is a register variable with an ASMSPEC . In that case , or
if the variable is not an automatic , it sets up the RTL and
outputs any assembler code ( label definition , storage allocation
and initialization ) .
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
DECL is the declaration . If ASMSPEC is nonzero , it specifies
the assembler symbol name to be used . TOP_LEVEL is nonzero
if this declaration is not within a function . */
1996-09-18 05:35:50 +00:00
void
2002-02-06 04:59:39 +00:00
rest_of_decl_compilation ( decl , asmspec , top_level , at_end )
tree decl ;
const char * asmspec ;
int top_level ;
int at_end ;
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
/* Declarations of variables, and of functions defined elsewhere. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* The most obvious approach, to put an #ifndef around where
this macro is used , doesn ' t work since it ' s inside a macro call . */
# ifndef ASM_FINISH_DECLARE_OBJECT
# define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP, END)
1996-09-18 05:35:50 +00:00
# endif
2002-09-01 21:06:42 +00:00
/* We deferred calling assemble_alias so that we could collect
other attributes such as visibility . Emit the alias now . */
{
tree alias ;
alias = lookup_attribute ( " alias " , DECL_ATTRIBUTES ( decl ) ) ;
if ( alias )
{
alias = TREE_VALUE ( TREE_VALUE ( alias ) ) ;
alias = get_identifier ( TREE_STRING_POINTER ( alias ) ) ;
assemble_alias ( decl , alias ) ;
}
}
2002-02-06 04:59:39 +00:00
/* Forward declarations for nested functions are not "external",
but we need to treat them as if they were . */
if ( TREE_STATIC ( decl ) | | DECL_EXTERNAL ( decl )
| | TREE_CODE ( decl ) = = FUNCTION_DECL )
{
timevar_push ( TV_VARCONST ) ;
if ( asmspec )
make_decl_rtl ( decl , asmspec ) ;
/* Don't output anything
when a tentative file - scope definition is seen .
But at end of compilation , do output code for them . */
if ( at_end | | ! DECL_DEFER_OUTPUT ( decl ) )
assemble_variable ( decl , top_level , at_end , 0 ) ;
if ( decl = = last_assemble_variable_decl )
{
ASM_FINISH_DECLARE_OBJECT ( asm_out_file , decl ,
top_level , at_end ) ;
}
timevar_pop ( TV_VARCONST ) ;
}
else if ( DECL_REGISTER ( decl ) & & asmspec ! = 0 )
{
if ( decode_reg_name ( asmspec ) > = 0 )
{
SET_DECL_RTL ( decl , NULL_RTX ) ;
make_decl_rtl ( decl , asmspec ) ;
}
else
{
error ( " invalid register name `%s' for register variable " , asmspec ) ;
DECL_REGISTER ( decl ) = 0 ;
if ( ! top_level )
expand_decl ( decl ) ;
}
}
# if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
else if ( ( write_symbols = = DBX_DEBUG | | write_symbols = = XCOFF_DEBUG )
& & TREE_CODE ( decl ) = = TYPE_DECL )
{
timevar_push ( TV_SYMOUT ) ;
dbxout_symbol ( decl , 0 ) ;
timevar_pop ( TV_SYMOUT ) ;
}
# endif
# ifdef SDB_DEBUGGING_INFO
else if ( write_symbols = = SDB_DEBUG & & top_level
& & TREE_CODE ( decl ) = = TYPE_DECL )
{
timevar_push ( TV_SYMOUT ) ;
sdbout_symbol ( decl , 0 ) ;
timevar_pop ( TV_SYMOUT ) ;
}
1996-09-18 05:35:50 +00:00
# endif
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
/* Called after finishing a record, union or enumeral type. */
1996-09-18 05:35:50 +00:00
void
2002-02-06 04:59:39 +00:00
rest_of_type_compilation ( type , toplev )
# if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO) || defined (SDB_DEBUGGING_INFO)
tree type ;
int toplev ;
# else
tree type ATTRIBUTE_UNUSED ;
int toplev ATTRIBUTE_UNUSED ;
# endif
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
timevar_push ( TV_SYMOUT ) ;
# if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if ( write_symbols = = DBX_DEBUG | | write_symbols = = XCOFF_DEBUG )
dbxout_symbol ( TYPE_STUB_DECL ( type ) , ! toplev ) ;
# endif
# ifdef SDB_DEBUGGING_INFO
if ( write_symbols = = SDB_DEBUG )
sdbout_symbol ( TYPE_STUB_DECL ( type ) , ! toplev ) ;
# endif
# ifdef DWARF2_DEBUGGING_INFO
if ( ( write_symbols = = DWARF2_DEBUG
| | write_symbols = = VMS_AND_DWARF2_DEBUG )
& & toplev )
dwarf2out_decl ( TYPE_STUB_DECL ( type ) ) ;
# endif
timevar_pop ( TV_SYMOUT ) ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* This is called from finish_function (within yyparse)
after each top - level definition is parsed .
It is supposed to compile that function or variable
and output the assembler code for it .
After we return , the tree storage is freed . */
1996-09-18 05:35:50 +00:00
void
2002-02-06 04:59:39 +00:00
rest_of_compilation ( decl )
tree decl ;
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
rtx insns ;
int tem ;
int failure = 0 ;
int rebuild_label_notes_after_reload ;
int register_life_up_to_date ;
2002-05-09 22:15:04 +00:00
int cleanup_crossjump ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_REST_OF_COMPILATION ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Now that we're out of the frontend, we shouldn't have any more
CONCATs anywhere . */
generating_concat_p = 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* When processing delayed functions, prepare_function_start() won't
have been run to re - initialize it . */
cse_not_expected = ! optimize ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* First, make sure that NOTE_BLOCK is set correctly for each
NOTE_INSN_BLOCK_BEG / NOTE_INSN_BLOCK_END note . */
if ( ! cfun - > x_whole_function_mode_p )
identify_blocks ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* In function-at-a-time mode, we do not attempt to keep the BLOCK
tree in sensible shape . So , we just recalculate it here . */
if ( cfun - > x_whole_function_mode_p )
reorder_blocks ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
init_flow ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* If we are reconsidering an inline function
at the end of compilation , skip the stuff for making it inline . */
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
if ( DECL_SAVED_INSNS ( decl ) = = 0 )
{
int inlinable = 0 ;
tree parent ;
const char * lose ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* If this is nested inside an inlined external function, pretend
it was only declared . Since we cannot inline such functions ,
generating code for this one is not only not necessary but will
confuse some debugging output writers . */
for ( parent = DECL_CONTEXT ( current_function_decl ) ;
parent ! = NULL_TREE ;
parent = get_containing_scope ( parent ) )
if ( TREE_CODE ( parent ) = = FUNCTION_DECL
& & DECL_INLINE ( parent ) & & DECL_EXTERNAL ( parent ) )
{
DECL_INITIAL ( decl ) = 0 ;
goto exit_rest_of_compilation ;
}
2002-12-04 15:59:56 +00:00
else if ( TYPE_P ( parent ) )
/* A function in a local class should be treated normally. */
break ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* If requested, consider whether to make this function inline. */
if ( ( DECL_INLINE ( decl ) & & ! flag_no_inline )
| | flag_inline_functions )
{
timevar_push ( TV_INTEGRATION ) ;
lose = function_cannot_inline_p ( decl ) ;
timevar_pop ( TV_INTEGRATION ) ;
if ( lose | | ! optimize )
{
if ( warn_inline & & DECL_INLINE ( decl ) )
warning_with_decl ( decl , lose ) ;
DECL_ABSTRACT_ORIGIN ( decl ) = 0 ;
/* Don't really compile an extern inline function.
If we can ' t make it inline , pretend
it was only declared . */
if ( DECL_EXTERNAL ( decl ) )
{
DECL_INITIAL ( decl ) = 0 ;
goto exit_rest_of_compilation ;
}
}
else
/* ??? Note that this has the effect of making it look
like " inline " was specified for a function if we choose
to inline it . This isn ' t quite right , but it ' s
probably not worth the trouble to fix . */
inlinable = DECL_INLINE ( decl ) = 1 ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
insns = get_insns ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Dump the rtl code if we are dumping rtl. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( open_dump_file ( DFI_rtl , decl ) )
{
if ( DECL_SAVED_INSNS ( decl ) )
fprintf ( rtl_dump_file , " ;; (integrable) \n \n " ) ;
close_dump_file ( DFI_rtl , print_rtl , insns ) ;
}
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Convert from NOTE_INSN_EH_REGION style notes, and do other
sorts of eh initialization . Delay this until after the
initial rtl dump so that we can see the original nesting . */
convert_from_eh_region_ranges ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* If function is inline, and we don't yet know whether to
compile it by itself , defer decision till end of compilation .
finish_compilation will call rest_of_compilation again
for those functions that need to be output . Also defer those
functions that we are supposed to defer . */
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
if ( inlinable
| | ( DECL_INLINE ( decl )
& & ( ( ! TREE_PUBLIC ( decl ) & & ! TREE_ADDRESSABLE ( decl )
2002-05-09 22:15:04 +00:00
& & ! TREE_SYMBOL_REFERENCED ( DECL_ASSEMBLER_NAME ( decl ) )
2002-02-06 04:59:39 +00:00
& & ! flag_keep_inline_functions )
| | DECL_EXTERNAL ( decl ) ) ) )
DECL_DEFER_OUTPUT ( decl ) = 1 ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
if ( DECL_INLINE ( decl ) )
/* DWARF wants separate debugging info for abstract and
concrete instances of all inline functions , including those
declared inline but not inlined , and those inlined even
though they weren ' t declared inline . Conveniently , that ' s
what DECL_INLINE means at this point . */
( * debug_hooks - > deferred_inline_function ) ( decl ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
if ( DECL_DEFER_OUTPUT ( decl ) )
{
/* If -Wreturn-type, we have to do a bit of compilation. We just
want to call cleanup the cfg to figure out whether or not we can
fall off the end of the function ; we do the minimum amount of
work necessary to make that safe . */
if ( warn_return_type )
{
int saved_optimize = optimize ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
optimize = 0 ;
rebuild_jump_labels ( insns ) ;
find_exception_handler_labels ( ) ;
find_basic_blocks ( insns , max_reg_num ( ) , rtl_dump_file ) ;
cleanup_cfg ( CLEANUP_PRE_SIBCALL | CLEANUP_PRE_LOOP ) ;
optimize = saved_optimize ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* CFG is no longer maintained up-to-date. */
free_bb_for_insn ( ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
current_function_nothrow = nothrow_function_p ( ) ;
if ( current_function_nothrow )
/* Now we know that this can't throw; set the flag for the benefit
of other functions later in this translation unit . */
TREE_NOTHROW ( current_function_decl ) = 1 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_INTEGRATION ) ;
save_for_inline ( decl ) ;
timevar_pop ( TV_INTEGRATION ) ;
DECL_SAVED_INSNS ( decl ) - > inlinable = inlinable ;
goto exit_rest_of_compilation ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* If specified extern inline but we aren't inlining it, we are
done . This goes for anything that gets here with DECL_EXTERNAL
set , not just things with DECL_INLINE . */
if ( DECL_EXTERNAL ( decl ) )
goto exit_rest_of_compilation ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* If we're emitting a nested function, make sure its parent gets
emitted as well . Doing otherwise confuses debug info . */
{
tree parent ;
for ( parent = DECL_CONTEXT ( current_function_decl ) ;
parent ! = NULL_TREE ;
parent = get_containing_scope ( parent ) )
if ( TREE_CODE ( parent ) = = FUNCTION_DECL )
TREE_SYMBOL_REFERENCED ( DECL_ASSEMBLER_NAME ( parent ) ) = 1 ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* We are now committed to emitting code for this function. Do any
preparation , such as emitting abstract debug info for the inline
before it gets mangled by optimization . */
if ( DECL_INLINE ( decl ) )
( * debug_hooks - > outlining_inline_function ) ( decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Remove any notes we don't need. That will make iterating
over the instruction sequence faster , and allow the garbage
collector to reclaim the memory used by the notes . */
remove_unnecessary_notes ( ) ;
reorder_blocks ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
ggc_collect ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Initialize some variables used by the optimizers. */
init_function_for_compilation ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
if ( ! DECL_DEFER_OUTPUT ( decl ) )
TREE_ASM_WRITTEN ( decl ) = 1 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Now that integrate will no longer see our rtl, we need not
distinguish between the return value of this function and the
return value of called functions . Also , we can remove all SETs
of subregs of hard registers ; they are only here because of
integrate . Also , we can now initialize pseudos intended to
carry magic hard reg data throughout the function . */
rtx_equal_function_value_matters = 0 ;
purge_hard_subreg_sets ( get_insns ( ) ) ;
1999-08-30 04:01:02 +00:00
2002-05-09 22:15:04 +00:00
/* Early return if there were errors. We can run afoul of our
consistency checks , and there ' s not really much point in fixing them .
Don ' t return yet if - Wreturn - type ; we need to do cleanup_cfg . */
if ( ( ( rtl_dump_and_exit | | flag_syntax_only ) & & ! warn_return_type )
| | errorcount | | sorrycount )
2002-02-06 04:59:39 +00:00
goto exit_rest_of_compilation ;
/* We may have potential sibling or tail recursion sites. Select one
( of possibly multiple ) methods of performing the call . */
if ( flag_optimize_sibling_calls )
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
timevar_push ( TV_JUMP ) ;
open_dump_file ( DFI_sibling , decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
optimize_sibling_and_tail_recursive_calls ( ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_sibling , print_rtl , get_insns ( ) ) ;
timevar_pop ( TV_JUMP ) ;
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
/* Complete generation of exception handling code. */
find_exception_handler_labels ( ) ;
if ( doing_eh ( 0 ) )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
timevar_push ( TV_JUMP ) ;
open_dump_file ( DFI_eh , decl ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
finish_eh_generation ( ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_eh , print_rtl , get_insns ( ) ) ;
timevar_pop ( TV_JUMP ) ;
}
1996-09-18 05:35:50 +00:00
2002-05-09 22:15:04 +00:00
/* Delay emitting hard_reg_initial_value sets until after EH landing pad
generation , which might create new sets . */
emit_initial_value_sets ( ) ;
2002-02-06 04:59:39 +00:00
# ifdef FINALIZE_PIC
/* If we are doing position-independent code generation, now
is the time to output special prologues and epilogues .
We do not want to do this earlier , because it just clutters
up inline functions with meaningless insns . */
if ( flag_pic )
FINALIZE_PIC ;
# endif
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
insns = get_insns ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Copy any shared structure that should not be shared. */
unshare_all_rtl ( current_function_decl , insns ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
# ifdef SETJMP_VIA_SAVE_AREA
/* This must be performed before virtual register instantiation. */
if ( current_function_calls_alloca )
optimize_save_area_alloca ( insns ) ;
# endif
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Instantiate all virtual registers. */
instantiate_virtual_regs ( current_function_decl , insns ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
open_dump_file ( DFI_jump , decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Always do one jump optimization pass to ensure that JUMP_LABEL fields
are initialized and to compute whether control can drop off the end
of the function . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_JUMP ) ;
/* Turn NOTE_INSN_EXPECTED_VALUE into REG_BR_PROB. Do this
before jump optimization switches branch directions . */
expected_value_to_br_prob ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
reg_scan ( insns , max_reg_num ( ) , 0 ) ;
rebuild_jump_labels ( insns ) ;
find_basic_blocks ( insns , max_reg_num ( ) , rtl_dump_file ) ;
cleanup_cfg ( ( optimize ? CLEANUP_EXPENSIVE : 0 ) | CLEANUP_PRE_LOOP ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* CFG is no longer maintained up-to-date. */
free_bb_for_insn ( ) ;
copy_loop_headers ( insns ) ;
purge_line_number_notes ( insns ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
timevar_pop ( TV_JUMP ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Now is when we stop if -fsyntax-only and -Wreturn-type. */
if ( rtl_dump_and_exit | | flag_syntax_only | | DECL_DEFER_OUTPUT ( decl ) )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_jump , print_rtl , insns ) ;
goto exit_rest_of_compilation ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Long term, this should probably move before the jump optimizer too,
but I didn ' t want to disturb the rtl_dump_and_exit and related
stuff at this time . */
if ( optimize > 0 & & flag_ssa )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
/* Convert to SSA form. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_TO_SSA ) ;
open_dump_file ( DFI_ssa , decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
find_basic_blocks ( insns , max_reg_num ( ) , rtl_dump_file ) ;
cleanup_cfg ( CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP ) ;
convert_to_ssa ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_ssa , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_TO_SSA ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Perform sparse conditional constant propagation, if requested. */
if ( flag_ssa_ccp )
{
timevar_push ( TV_SSA_CCP ) ;
open_dump_file ( DFI_ssa_ccp , decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
ssa_const_prop ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_ssa_ccp , print_rtl_with_bb , get_insns ( ) ) ;
timevar_pop ( TV_SSA_CCP ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* It would be useful to cleanup the CFG at this point, but block
merging and possibly other transformations might leave a PHI
node in the middle of a basic block , which is a strict no - no . */
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* The SSA implementation uses basic block numbers in its phi
nodes . Thus , changing the control - flow graph or the basic
blocks , e . g . , calling find_basic_blocks ( ) or cleanup_cfg ( ) ,
may cause problems . */
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
if ( flag_ssa_dce )
{
/* Remove dead code. */
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_SSA_DCE ) ;
open_dump_file ( DFI_ssa_dce , decl ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
insns = get_insns ( ) ;
ssa_eliminate_dead_code ( ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_ssa_dce , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_SSA_DCE ) ;
}
/* Convert from SSA form. */
timevar_push ( TV_FROM_SSA ) ;
open_dump_file ( DFI_ussa , decl ) ;
convert_from_ssa ( ) ;
/* New registers have been created. Rescan their usage. */
reg_scan ( insns , max_reg_num ( ) , 1 ) ;
close_dump_file ( DFI_ussa , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_FROM_SSA ) ;
ggc_collect ( ) ;
/* CFG is no longer maintained up-to-date. */
free_bb_for_insn ( ) ;
}
timevar_push ( TV_JUMP ) ;
if ( optimize > 0 )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
find_basic_blocks ( insns , max_reg_num ( ) , rtl_dump_file ) ;
cleanup_cfg ( CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP
| ( flag_thread_jumps ? CLEANUP_THREADING : 0 ) ) ;
/* ??? Run if-conversion before delete_null_pointer_checks,
since the later does not preserve the CFG . This should
be changed - - no since converting if ' s that are going to
be deleted . */
timevar_push ( TV_IFCVT ) ;
if_convert ( 0 ) ;
timevar_pop ( TV_IFCVT ) ;
/* CFG is no longer maintained up-to-date. */
free_bb_for_insn ( ) ;
/* Try to identify useless null pointer tests and delete them. */
if ( flag_delete_null_pointer_checks )
delete_null_pointer_checks ( insns ) ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
/* Jump optimization, and the removal of NULL pointer checks, may
have reduced the number of instructions substantially . CSE , and
future passes , allocate arrays whose dimensions involve the
maximum instruction UID , so if we can reduce the maximum UID
we ' ll save big on memory . */
renumber_insns ( rtl_dump_file ) ;
timevar_pop ( TV_JUMP ) ;
close_dump_file ( DFI_jump , print_rtl , insns ) ;
ggc_collect ( ) ;
/* Perform common subexpression elimination.
Nonzero value from ` cse_main ' means that jumps were simplified
and some code may now be unreachable , so do
jump optimization again . */
if ( optimize > 0 )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
open_dump_file ( DFI_cse , decl ) ;
timevar_push ( TV_CSE ) ;
reg_scan ( insns , max_reg_num ( ) , 1 ) ;
tem = cse_main ( insns , max_reg_num ( ) , 0 , rtl_dump_file ) ;
/* If we are not running more CSE passes, then we are no longer
expecting CSE to be run . But always rerun it in a cheap mode . */
cse_not_expected = ! flag_rerun_cse_after_loop & & ! flag_gcse ;
if ( tem | | optimize > 1 )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
timevar_push ( TV_JUMP ) ;
rebuild_jump_labels ( insns ) ;
find_basic_blocks ( insns , max_reg_num ( ) , rtl_dump_file ) ;
cleanup_cfg ( CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP ) ;
timevar_pop ( TV_JUMP ) ;
/* CFG is no longer maintained up-to-date. */
free_bb_for_insn ( ) ;
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
/* Run this after jump optmizations remove all the unreachable code
so that unreachable code will not keep values live . */
delete_trivially_dead_insns ( insns , max_reg_num ( ) , 0 ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
/* Try to identify useless null pointer tests and delete them. */
if ( flag_delete_null_pointer_checks | | flag_thread_jumps )
{
timevar_push ( TV_JUMP ) ;
find_basic_blocks ( insns , max_reg_num ( ) , rtl_dump_file ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
cleanup_cfg ( CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP
| ( flag_thread_jumps ? CLEANUP_THREADING : 0 ) ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
if ( flag_delete_null_pointer_checks )
delete_null_pointer_checks ( insns ) ;
/* CFG is no longer maintained up-to-date. */
free_bb_for_insn ( ) ;
timevar_pop ( TV_JUMP ) ;
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
/* The second pass of jump optimization is likely to have
removed a bunch more instructions . */
renumber_insns ( rtl_dump_file ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
timevar_pop ( TV_CSE ) ;
close_dump_file ( DFI_cse , print_rtl , insns ) ;
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
open_dump_file ( DFI_addressof , decl ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
purge_addressof ( insns ) ;
reg_scan ( insns , max_reg_num ( ) , 1 ) ;
close_dump_file ( DFI_addressof , print_rtl , insns ) ;
ggc_collect ( ) ;
/* Perform global cse. */
if ( optimize > 0 & & flag_gcse )
{
int save_csb , save_cfj ;
int tem2 = 0 ;
timevar_push ( TV_GCSE ) ;
open_dump_file ( DFI_gcse , decl ) ;
find_basic_blocks ( insns , max_reg_num ( ) , rtl_dump_file ) ;
cleanup_cfg ( CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP ) ;
tem = gcse_main ( insns , rtl_dump_file ) ;
rebuild_jump_labels ( insns ) ;
save_csb = flag_cse_skip_blocks ;
save_cfj = flag_cse_follow_jumps ;
flag_cse_skip_blocks = flag_cse_follow_jumps = 0 ;
/* CFG is no longer maintained up-to-date. */
free_bb_for_insn ( ) ;
/* If -fexpensive-optimizations, re-run CSE to clean up things done
by gcse . */
if ( flag_expensive_optimizations )
{
timevar_push ( TV_CSE ) ;
reg_scan ( insns , max_reg_num ( ) , 1 ) ;
tem2 = cse_main ( insns , max_reg_num ( ) , 0 , rtl_dump_file ) ;
timevar_pop ( TV_CSE ) ;
cse_not_expected = ! flag_rerun_cse_after_loop ;
}
/* If gcse or cse altered any jumps, rerun jump optimizations to clean
things up . Then possibly re - run CSE again . */
while ( tem | | tem2 )
{
tem = tem2 = 0 ;
timevar_push ( TV_JUMP ) ;
rebuild_jump_labels ( insns ) ;
delete_trivially_dead_insns ( insns , max_reg_num ( ) , 0 ) ;
find_basic_blocks ( insns , max_reg_num ( ) , rtl_dump_file ) ;
cleanup_cfg ( CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP ) ;
/* CFG is no longer maintained up-to-date. */
free_bb_for_insn ( ) ;
timevar_pop ( TV_JUMP ) ;
if ( flag_expensive_optimizations )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
timevar_push ( TV_CSE ) ;
reg_scan ( insns , max_reg_num ( ) , 1 ) ;
tem2 = cse_main ( insns , max_reg_num ( ) , 0 , rtl_dump_file ) ;
timevar_pop ( TV_CSE ) ;
1999-10-27 09:31:52 +00:00
}
}
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_gcse , print_rtl , insns ) ;
timevar_pop ( TV_GCSE ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
ggc_collect ( ) ;
flag_cse_skip_blocks = save_csb ;
flag_cse_follow_jumps = save_cfj ;
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
/* Move constant computations out of loops. */
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
if ( optimize > 0 )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
timevar_push ( TV_LOOP ) ;
open_dump_file ( DFI_loop , decl ) ;
free_bb_for_insn ( ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
if ( flag_rerun_loop_opt )
{
cleanup_barriers ( ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
/* We only want to perform unrolling once. */
2002-05-09 22:15:04 +00:00
loop_optimize ( insns , rtl_dump_file , LOOP_FIRST_PASS ) ;
2002-02-06 04:59:39 +00:00
/* The first call to loop_optimize makes some instructions
trivially dead . We delete those instructions now in the
hope that doing so will make the heuristics in loop work
better and possibly speed up compilation . */
delete_trivially_dead_insns ( insns , max_reg_num ( ) , 0 ) ;
/* The regscan pass is currently necessary as the alias
analysis code depends on this information . */
reg_scan ( insns , max_reg_num ( ) , 1 ) ;
}
cleanup_barriers ( ) ;
loop_optimize ( insns , rtl_dump_file ,
( flag_unroll_loops ? LOOP_UNROLL : 0 ) | LOOP_BCT
| ( flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0 ) ) ;
close_dump_file ( DFI_loop , print_rtl , insns ) ;
timevar_pop ( TV_LOOP ) ;
ggc_collect ( ) ;
}
if ( optimize > 0 )
{
timevar_push ( TV_CSE2 ) ;
open_dump_file ( DFI_cse2 , decl ) ;
if ( flag_rerun_cse_after_loop )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
/* Running another jump optimization pass before the second
cse pass sometimes simplifies the RTL enough to allow
the second CSE pass to do a better job . Jump_optimize can change
max_reg_num so we must rerun reg_scan afterwards .
? ? ? Rework to not call reg_scan so often . */
timevar_push ( TV_JUMP ) ;
/* The previous call to loop_optimize makes some instructions
trivially dead . We delete those instructions now in the
hope that doing so will make the heuristics in jump work
better and possibly speed up compilation . */
delete_trivially_dead_insns ( insns , max_reg_num ( ) , 0 ) ;
reg_scan ( insns , max_reg_num ( ) , 0 ) ;
timevar_push ( TV_IFCVT ) ;
find_basic_blocks ( insns , max_reg_num ( ) , rtl_dump_file ) ;
cleanup_cfg ( CLEANUP_EXPENSIVE ) ;
if_convert ( 0 ) ;
timevar_pop ( TV_IFCVT ) ;
timevar_pop ( TV_JUMP ) ;
/* CFG is no longer maintained up-to-date. */
free_bb_for_insn ( ) ;
reg_scan ( insns , max_reg_num ( ) , 0 ) ;
tem = cse_main ( insns , max_reg_num ( ) , 1 , rtl_dump_file ) ;
if ( tem )
{
timevar_push ( TV_JUMP ) ;
rebuild_jump_labels ( insns ) ;
find_basic_blocks ( insns , max_reg_num ( ) , rtl_dump_file ) ;
cleanup_cfg ( CLEANUP_EXPENSIVE ) ;
/* CFG is no longer maintained up-to-date. */
free_bb_for_insn ( ) ;
timevar_pop ( TV_JUMP ) ;
}
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_cse2 , print_rtl , insns ) ;
timevar_pop ( TV_CSE2 ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
ggc_collect ( ) ;
1999-10-27 09:31:52 +00:00
}
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
cse_not_expected = 1 ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
regclass_init ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Do control and data flow analysis; wrote some of the results to
the dump file . */
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_FLOW ) ;
open_dump_file ( DFI_cfg , decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
find_basic_blocks ( insns , max_reg_num ( ) , rtl_dump_file ) ;
cleanup_cfg ( ( optimize ? CLEANUP_EXPENSIVE : 0 )
| ( flag_thread_jumps ? CLEANUP_THREADING : 0 ) ) ;
check_function_return_warnings ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* It may make more sense to mark constant functions after dead code is
eliminated by life_analyzis , but we need to do it early , as - fprofile - arcs
may insert code making function non - constant , but we still must consider
it as constant , otherwise - fbranch - probabilities will not read data back .
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
life_analyzis rarely eliminates modification of external memory .
*/
mark_constant_function ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_cfg , print_rtl_with_bb , insns ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( profile_arc_flag | | flag_test_coverage | | flag_branch_probabilities )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
timevar_push ( TV_BRANCH_PROB ) ;
open_dump_file ( DFI_bp , decl ) ;
branch_prob ( ) ;
close_dump_file ( DFI_bp , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_BRANCH_PROB ) ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
open_dump_file ( DFI_life , decl ) ;
if ( optimize )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
struct loops loops ;
/* Discover and record the loop depth at the head of each basic
block . The loop infrastructure does the real job for us . */
flow_loops_find ( & loops , LOOP_TREE ) ;
2002-10-10 04:51:11 +00:00
if ( rtl_dump_file )
flow_loops_dump ( & loops , rtl_dump_file , NULL , 0 ) ;
2002-02-06 04:59:39 +00:00
/* Estimate using heuristics if no profiling info is available. */
if ( flag_guess_branch_prob )
estimate_probability ( & loops ) ;
flow_loops_free ( & loops ) ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
life_analysis ( insns , rtl_dump_file , PROP_FINAL ) ;
timevar_pop ( TV_FLOW ) ;
no_new_pseudos = 1 ;
if ( warn_uninitialized | | extra_warnings )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
uninitialized_vars_warning ( DECL_INITIAL ( decl ) ) ;
if ( extra_warnings )
setjmp_args_warning ( ) ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
if ( optimize )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
if ( initialize_uninitialized_subregs ( ) )
{
/* Insns were inserted, so things might look a bit different. */
insns = get_insns ( ) ;
life_analysis ( insns , rtl_dump_file ,
( PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES ) ) ;
}
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_life , print_rtl_with_bb , insns ) ;
ggc_collect ( ) ;
/* If -opt, try combining insns through substitution. */
if ( optimize > 0 )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
int rebuild_jump_labels_after_combine = 0 ;
timevar_push ( TV_COMBINE ) ;
open_dump_file ( DFI_combine , decl ) ;
rebuild_jump_labels_after_combine
= combine_instructions ( insns , max_reg_num ( ) ) ;
/* Always purge dead edges, as we may eliminate an insn throwing
exception . */
rebuild_jump_labels_after_combine | = purge_all_dead_edges ( true ) ;
/* Combining insns may have turned an indirect jump into a
direct jump . Rebuid the JUMP_LABEL fields of jumping
instructions . */
if ( rebuild_jump_labels_after_combine )
{
timevar_push ( TV_JUMP ) ;
rebuild_jump_labels ( insns ) ;
timevar_pop ( TV_JUMP ) ;
cleanup_cfg ( CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE ) ;
}
close_dump_file ( DFI_combine , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_COMBINE ) ;
ggc_collect ( ) ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
/* Rerun if-conversion, as combine may have simplified things enough to
now meet sequence length restrictions . */
if ( optimize > 0 )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
timevar_push ( TV_IFCVT ) ;
open_dump_file ( DFI_ce , decl ) ;
no_new_pseudos = 0 ;
if_convert ( 1 ) ;
no_new_pseudos = 1 ;
close_dump_file ( DFI_ce , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_IFCVT ) ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
/* Register allocation pre-pass, to reduce number of moves
necessary for two - address machines . */
if ( optimize > 0 & & ( flag_regmove | | flag_expensive_optimizations ) )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
timevar_push ( TV_REGMOVE ) ;
open_dump_file ( DFI_regmove , decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
regmove_optimize ( insns , max_reg_num ( ) , rtl_dump_file ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_regmove , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_REGMOVE ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
ggc_collect ( ) ;
1999-10-27 09:31:52 +00:00
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Do unconditional splitting before register allocation to allow machine
description to add extra information not needed previously . */
split_all_insns ( 1 ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Any of the several passes since flow1 will have munged register
lifetime data a bit . */
register_life_up_to_date = 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
# ifdef OPTIMIZE_MODE_SWITCHING
timevar_push ( TV_MODE_SWITCH ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
no_new_pseudos = 0 ;
if ( optimize_mode_switching ( NULL ) )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
/* We did work, and so had to regenerate global life information.
Take advantage of this and don ' t re - recompute register life
information below . */
register_life_up_to_date = 1 ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
no_new_pseudos = 1 ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
timevar_pop ( TV_MODE_SWITCH ) ;
1999-08-30 04:01:02 +00:00
# endif
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_SCHED ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
# ifdef INSN_SCHEDULING
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Print function header into sched dump now
because doing the sched analysis makes some of the dump . */
if ( optimize > 0 & & flag_schedule_insns )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
open_dump_file ( DFI_sched , decl ) ;
/* Do control and data sched analysis,
and write some of the results to dump file . */
schedule_insns ( rtl_dump_file ) ;
close_dump_file ( DFI_sched , print_rtl_with_bb , insns ) ;
/* Register lifetime information was updated as part of verifying
the schedule . */
register_life_up_to_date = 1 ;
1999-10-27 09:31:52 +00:00
}
1999-08-30 04:01:02 +00:00
# endif
2002-02-06 04:59:39 +00:00
timevar_pop ( TV_SCHED ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
ggc_collect ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Determine if the current function is a leaf before running reload
since this can impact optimizations done by the prologue and
epilogue thus changing register elimination offsets . */
current_function_is_leaf = leaf_function_p ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_LOCAL_ALLOC ) ;
open_dump_file ( DFI_lreg , decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Allocate pseudo-regs that are used only within 1 basic block.
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
RUN_JUMP_AFTER_RELOAD records whether or not we need to rerun the
jump optimizer after register allocation and reloading are finished . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( ! register_life_up_to_date )
recompute_reg_usage ( insns , ! optimize_size ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Allocate the reg_renumber array. */
allocate_reg_info ( max_regno , FALSE , TRUE ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* And the reg_equiv_memory_loc array. */
reg_equiv_memory_loc = ( rtx * ) xcalloc ( max_regno , sizeof ( rtx ) ) ;
allocate_initial_values ( reg_equiv_memory_loc ) ;
regclass ( insns , max_reg_num ( ) , rtl_dump_file ) ;
rebuild_label_notes_after_reload = local_alloc ( ) ;
timevar_pop ( TV_LOCAL_ALLOC ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( dump_file [ DFI_lreg ] . enabled )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
timevar_push ( TV_DUMP ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
dump_flow_info ( rtl_dump_file ) ;
dump_local_alloc ( rtl_dump_file ) ;
close_dump_file ( DFI_lreg , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_DUMP ) ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
ggc_collect ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_GLOBAL_ALLOC ) ;
open_dump_file ( DFI_greg , decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* If optimizing, allocate remaining pseudo-regs. Do the reload
pass fixing up any insns that are invalid . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( optimize )
failure = global_alloc ( rtl_dump_file ) ;
else
{
build_insn_chain ( insns ) ;
failure = reload ( insns , 0 ) ;
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
timevar_pop ( TV_GLOBAL_ALLOC ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( dump_file [ DFI_greg ] . enabled )
{
timevar_push ( TV_DUMP ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
dump_global_regs ( rtl_dump_file ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_greg , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_DUMP ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( failure )
goto exit_rest_of_compilation ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
ggc_collect ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
open_dump_file ( DFI_postreload , decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Do a very simple CSE pass over just the hard registers. */
if ( optimize > 0 )
{
timevar_push ( TV_RELOAD_CSE_REGS ) ;
reload_cse_regs ( insns ) ;
timevar_pop ( TV_RELOAD_CSE_REGS ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Register allocation and reloading may have turned an indirect jump into
a direct jump . If so , we must rebuild the JUMP_LABEL fields of
jumping instructions . */
if ( rebuild_label_notes_after_reload )
{
timevar_push ( TV_JUMP ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
rebuild_jump_labels ( insns ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
timevar_pop ( TV_JUMP ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_postreload , print_rtl_with_bb , insns ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Re-create the death notes which were deleted during reload. */
timevar_push ( TV_FLOW2 ) ;
open_dump_file ( DFI_flow2 , decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
# ifdef ENABLE_CHECKING
verify_flow_info ( ) ;
1996-09-18 05:35:50 +00:00
# endif
2002-02-06 04:59:39 +00:00
/* If optimizing, then go ahead and split insns now. */
if ( optimize > 0 )
split_all_insns ( 0 ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
cleanup_cfg ( optimize ? CLEANUP_EXPENSIVE : 0 ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* On some machines, the prologue and epilogue code, or parts thereof,
can be represented as RTL . Doing so lets us schedule insns between
it and the rest of the code and also allows delayed branch
scheduling to operate in the epilogue . */
thread_prologue_and_epilogue_insns ( insns ) ;
1999-08-30 04:01:02 +00:00
2002-05-09 22:15:04 +00:00
/* Cross-jumping is O(N^3) on the number of edges, thus trying to
perform cross - jumping on flow graphs which have a high connectivity
will take a long time . This is similar to the test to disable GCSE . */
cleanup_crossjump = CLEANUP_CROSSJUMP ;
if ( n_basic_blocks > 1000 & & n_edges / n_basic_blocks > = 20 )
{
if ( optimize & & warn_disabled_optimization )
warning ( " crossjump disabled: %d > 1000 basic blocks and %d >= 20 edges/basic block " ,
n_basic_blocks , n_edges / n_basic_blocks ) ;
cleanup_crossjump = 0 ;
}
2002-02-06 04:59:39 +00:00
if ( optimize )
{
2002-05-09 22:15:04 +00:00
cleanup_cfg ( CLEANUP_EXPENSIVE | cleanup_crossjump ) ;
2002-02-06 04:59:39 +00:00
life_analysis ( insns , rtl_dump_file , PROP_FINAL ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* This is kind of a heuristic. We need to run combine_stack_adjustments
even for machines with possibly nonzero RETURN_POPS_ARGS
and ACCUMULATE_OUTGOING_ARGS . We expect that only ports having
push instructions will have popping returns . */
# ifndef PUSH_ROUNDING
if ( ! ACCUMULATE_OUTGOING_ARGS )
1996-09-18 05:35:50 +00:00
# endif
2002-02-06 04:59:39 +00:00
combine_stack_adjustments ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
ggc_collect ( ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
flow2_completed = 1 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_flow2 , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_FLOW2 ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
# ifdef HAVE_peephole2
if ( optimize > 0 & & flag_peephole2 )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
timevar_push ( TV_PEEPHOLE2 ) ;
open_dump_file ( DFI_peephole2 , decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
peephole2_optimize ( rtl_dump_file ) ;
close_dump_file ( DFI_peephole2 , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_PEEPHOLE2 ) ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
# endif
1996-09-18 05:35:50 +00:00
2002-05-09 22:15:04 +00:00
if ( optimize > 0 & & ( flag_rename_registers | | flag_cprop_registers ) )
2002-02-06 04:59:39 +00:00
{
timevar_push ( TV_RENAME_REGISTERS ) ;
open_dump_file ( DFI_rnreg , decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( flag_rename_registers )
regrename_optimize ( ) ;
if ( flag_cprop_registers )
copyprop_hardreg_forward ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_rnreg , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_RENAME_REGISTERS ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( optimize > 0 )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
timevar_push ( TV_IFCVT2 ) ;
open_dump_file ( DFI_ce2 , decl ) ;
if_convert ( 1 ) ;
close_dump_file ( DFI_ce2 , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_IFCVT2 ) ;
}
1999-10-27 09:31:52 +00:00
# ifdef STACK_REGS
2002-02-06 04:59:39 +00:00
if ( optimize )
split_all_insns ( 1 ) ;
1999-10-27 09:31:52 +00:00
# endif
2002-02-06 04:59:39 +00:00
# ifdef INSN_SCHEDULING
if ( optimize > 0 & & flag_schedule_insns_after_reload )
{
timevar_push ( TV_SCHED2 ) ;
open_dump_file ( DFI_sched2 , decl ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
/* Do control and data sched analysis again,
and write some more of the results to dump file . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
split_all_insns ( 1 ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
schedule_insns ( rtl_dump_file ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_sched2 , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_SCHED2 ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
ggc_collect ( ) ;
}
# endif
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
# ifdef LEAF_REGISTERS
current_function_uses_only_leaf_regs
= optimize > 0 & & only_leaf_regs_used ( ) & & leaf_function_p ( ) ;
1996-09-18 05:35:50 +00:00
# endif
2002-02-06 04:59:39 +00:00
# ifdef STACK_REGS
timevar_push ( TV_REG_STACK ) ;
open_dump_file ( DFI_stack , decl ) ;
reg_to_stack ( insns , rtl_dump_file ) ;
close_dump_file ( DFI_stack , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_REG_STACK ) ;
ggc_collect ( ) ;
# endif
if ( optimize > 0 )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
timevar_push ( TV_REORDER_BLOCKS ) ;
open_dump_file ( DFI_bbro , decl ) ;
2002-05-09 22:15:04 +00:00
/* Last attempt to optimize CFG, as life analysis possibly removed
some instructions . Note that we can ' t rerun crossjump at this
point , because it can turn a switch into a direct branch , which
can leave the tablejump address calculation in the code , which
can lead to referencing an undefined label . */
cleanup_cfg ( CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK ) ;
2002-02-06 04:59:39 +00:00
if ( flag_reorder_blocks )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
reorder_basic_blocks ( ) ;
cleanup_cfg ( CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK ) ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_bbro , print_rtl_with_bb , insns ) ;
timevar_pop ( TV_REORDER_BLOCKS ) ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
compute_alignments ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* CFG is no longer maintained up-to-date. */
free_bb_for_insn ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* If a machine dependent reorganization is needed, call it. */
# ifdef MACHINE_DEPENDENT_REORG
timevar_push ( TV_MACH_DEP ) ;
open_dump_file ( DFI_mach , decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
MACHINE_DEPENDENT_REORG ( insns ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_mach , print_rtl , insns ) ;
timevar_pop ( TV_MACH_DEP ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
ggc_collect ( ) ;
# endif
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
purge_line_number_notes ( insns ) ;
cleanup_barriers ( ) ;
/* If a scheduling pass for delayed branches is to be done,
call the scheduling code . */
# ifdef DELAY_SLOTS
if ( optimize > 0 & & flag_delayed_branch )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
timevar_push ( TV_DBR_SCHED ) ;
open_dump_file ( DFI_dbr , decl ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
dbr_schedule ( insns , rtl_dump_file ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
close_dump_file ( DFI_dbr , print_rtl , insns ) ;
timevar_pop ( TV_DBR_SCHED ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
ggc_collect ( ) ;
}
# endif
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
# if defined (HAVE_ATTR_length) && !defined (STACK_REGS)
timevar_push ( TV_SHORTEN_BRANCH ) ;
split_all_insns_noflow ( ) ;
timevar_pop ( TV_SHORTEN_BRANCH ) ;
# endif
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
convert_to_eh_region_ranges ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Shorten branches. */
timevar_push ( TV_SHORTEN_BRANCH ) ;
shorten_branches ( get_insns ( ) ) ;
timevar_pop ( TV_SHORTEN_BRANCH ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
current_function_nothrow = nothrow_function_p ( ) ;
if ( current_function_nothrow )
/* Now we know that this can't throw; set the flag for the benefit
of other functions later in this translation unit . */
TREE_NOTHROW ( current_function_decl ) = 1 ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Now turn the rtl into assembler code. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_FINAL ) ;
{
rtx x ;
const char * fnname ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Get the function's name, as described by its RTL. This may be
different from the DECL_NAME name used in the source file . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
x = DECL_RTL ( decl ) ;
if ( GET_CODE ( x ) ! = MEM )
abort ( ) ;
x = XEXP ( x , 0 ) ;
if ( GET_CODE ( x ) ! = SYMBOL_REF )
abort ( ) ;
fnname = XSTR ( x , 0 ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
assemble_start_function ( decl , fnname ) ;
final_start_function ( insns , asm_out_file , optimize ) ;
final ( insns , asm_out_file , optimize , 0 ) ;
final_end_function ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
# ifdef IA64_UNWIND_INFO
/* ??? The IA-64 ".handlerdata" directive must be issued before
the " .endp " directive that closes the procedure descriptor . */
output_function_exception_table ( ) ;
# endif
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
assemble_end_function ( decl , fnname ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
# ifndef IA64_UNWIND_INFO
/* Otherwise, it feels unclean to switch sections in the middle. */
output_function_exception_table ( ) ;
1996-09-18 05:35:50 +00:00
# endif
2002-02-06 04:59:39 +00:00
if ( ! quiet_flag )
fflush ( asm_out_file ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Release all memory allocated by flow. */
free_basic_block_vars ( 0 ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Release all memory held by regsets now. */
regset_release_memory ( ) ;
}
timevar_pop ( TV_FINAL ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
ggc_collect ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Write DBX symbols if requested. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Note that for those inline functions where we don't initially
know for certain that we will be generating an out - of - line copy ,
the first invocation of this routine ( rest_of_compilation ) will
skip over this code by doing a ` goto exit_rest_of_compilation ; ' .
Later on , finish_compilation will call rest_of_compilation again
for those inline functions that need to have out - of - line copies
generated . During that call , we * will * be routed past here . */
timevar_push ( TV_SYMOUT ) ;
( * debug_hooks - > function_decl ) ( decl ) ;
timevar_pop ( TV_SYMOUT ) ;
exit_rest_of_compilation :
/* In case the function was not output,
don ' t leave any temporary anonymous types
queued up for sdb output . */
# ifdef SDB_DEBUGGING_INFO
if ( write_symbols = = SDB_DEBUG )
sdbout_types ( NULL_TREE ) ;
1999-08-30 04:01:02 +00:00
# endif
2002-02-06 04:59:39 +00:00
reload_completed = 0 ;
flow2_completed = 0 ;
no_new_pseudos = 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_push ( TV_FINAL ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Clear out the insn_length contents now that they are no
longer valid . */
init_insn_lengths ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Clear out the real_constant_chain before some of the rtx's
it runs through become garbage . */
clear_const_double_mem ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Show no temporary slots allocated. */
init_temp_slots ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
free_basic_block_vars ( 0 ) ;
free_bb_for_insn ( ) ;
timevar_pop ( TV_FINAL ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Make sure volatile mem refs aren't considered valid operands for
arithmetic insns . We must call this here if this is a nested inline
function , since the above code leaves us in the init_recog state
( from final . c ) , and the function context push / pop code does not
save / restore volatile_ok .
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
? ? ? Maybe it isn ' t necessary for expand_start_function to call this
anymore if we do it here ? */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
init_recog_no_volatile ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* We're done with this function. Free up memory if we can. */
free_after_parsing ( cfun ) ;
if ( ! DECL_DEFER_OUTPUT ( decl ) )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
free_after_compilation ( cfun ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Clear integrate.c's pointer to the cfun structure we just
destroyed . */
DECL_SAVED_INSNS ( decl ) = 0 ;
}
cfun = 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
ggc_collect ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_pop ( TV_REST_OF_COMPILATION ) ;
}
static void
display_help ( )
{
int undoc ;
unsigned long i ;
const char * lang ;
printf ( _ ( " -ffixed-<register> Mark <register> as being unavailable to the compiler \n " ) ) ;
printf ( _ ( " -fcall-used-<register> Mark <register> as being corrupted by function calls \n " ) ) ;
printf ( _ ( " -fcall-saved-<register> Mark <register> as being preserved across functions \n " ) ) ;
printf ( _ ( " -finline-limit=<number> Limits the size of inlined functions to <number> \n " ) ) ;
printf ( _ ( " -fmessage-length=<number> Limits diagnostics messages lengths to <number> characters per line. 0 suppresses line-wrapping \n " ) ) ;
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 " ) ) ;
for ( i = ARRAY_SIZE ( f_options ) ; i - - ; )
{
const char * description = f_options [ i ] . description ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
if ( description ! = NULL & & * description ! = 0 )
printf ( " -f%-21s %s \n " ,
f_options [ i ] . string , _ ( description ) ) ;
}
2000-01-22 16:05:33 +00:00
2002-02-06 04:59:39 +00:00
printf ( _ ( " -O[number] Set optimization level to [number] \n " ) ) ;
printf ( _ ( " -Os Optimize for space rather than speed \n " ) ) ;
for ( i = LAST_PARAM ; i - - ; )
{
const char * description = compiler_params [ i ] . help ;
const int length = 21 - strlen ( compiler_params [ i ] . option ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
if ( description ! = NULL & & * description ! = 0 )
printf ( " --param %s=<value>%.*s%s \n " ,
compiler_params [ i ] . option ,
length > 0 ? length : 1 , " " ,
_ ( description ) ) ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
printf ( _ ( " -pedantic Issue warnings needed by strict compliance to ISO C \n " ) ) ;
printf ( _ ( " -pedantic-errors Like -pedantic except that errors are produced \n " ) ) ;
printf ( _ ( " -w Suppress warnings \n " ) ) ;
printf ( _ ( " -W Enable extra warnings \n " ) ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
for ( i = ARRAY_SIZE ( W_options ) ; i - - ; )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
const char * description = W_options [ i ] . description ;
if ( description ! = NULL & & * description ! = 0 )
printf ( " -W%-21s %s \n " ,
W_options [ i ] . string , _ ( description ) ) ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
printf ( _ ( " -Wunused Enable unused warnings \n " ) ) ;
printf ( _ ( " -Wlarger-than-<number> Warn if an object is larger than <number> bytes \n " ) ) ;
printf ( _ ( " -p Enable function profiling \n " ) ) ;
printf ( _ ( " -o <file> Place output into <file> \n " ) ) ;
printf ( _ ( " \
- G < number > Put global and static data smaller than < number > \ n \
bytes into a special section ( on some targets ) \ n " )) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
for ( i = ARRAY_SIZE ( debug_args ) ; i - - ; )
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
if ( debug_args [ i ] . description ! = NULL )
printf ( " -g%-21s %s \n " ,
debug_args [ i ] . arg , _ ( debug_args [ i ] . description ) ) ;
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
printf ( _ ( " -aux-info <file> Emit declaration info into <file> \n " ) ) ;
printf ( _ ( " -quiet Do not display functions compiled or elapsed time \n " ) ) ;
printf ( _ ( " -version Display the compiler's version \n " ) ) ;
printf ( _ ( " -d[letters] Enable dumps from specific passes of the compiler \n " ) ) ;
printf ( _ ( " -dumpbase <file> Base name to be used for dumps from specific passes \n " ) ) ;
# if defined INSN_SCHEDULING
printf ( _ ( " -fsched-verbose=<number> Set the verbosity level of the scheduler \n " ) ) ;
# endif
printf ( _ ( " --help Display this information \n " ) ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
undoc = 0 ;
lang = " language " ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Display descriptions of language specific options.
If there is no description , note that there is an undocumented option .
If the description is empty , do not display anything . ( This allows
options to be deliberately undocumented , for whatever reason ) .
If the option string is missing , then this is a marker , indicating
that the description string is in fact the name of a language , whose
language specific options are to follow . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( ARRAY_SIZE ( documented_lang_options ) > 1 )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
printf ( _ ( " \n Language specific options: \n " ) ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
for ( i = 0 ; i < ARRAY_SIZE ( documented_lang_options ) ; i + + )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
const char * description = documented_lang_options [ i ] . description ;
const char * option = documented_lang_options [ i ] . option ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( description = = NULL )
{
undoc = 1 ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
if ( extra_warnings )
printf ( _ ( " %-23.23s [undocumented] \n " ) , option ) ;
}
else if ( * description = = 0 )
continue ;
else if ( option = = NULL )
{
if ( undoc )
printf
( _ ( " \n There are undocumented %s specific options as well. \n " ) ,
lang ) ;
undoc = 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
printf ( _ ( " \n Options for %s: \n " ) , description ) ;
lang = description ;
}
else
printf ( " %-23.23s %s \n " , option , _ ( description ) ) ;
1999-08-30 04:01:02 +00:00
}
2002-02-06 04:59:39 +00:00
}
if ( undoc )
printf ( _ ( " \n There are undocumented %s specific options as well. \n " ) ,
lang ) ;
display_target_options ( ) ;
}
static void
display_target_options ( )
{
int undoc , i ;
static bool displayed = false ;
/* Avoid double printing for --help --target-help. */
if ( displayed )
return ;
displayed = true ;
if ( ARRAY_SIZE ( target_switches ) > 1
# ifdef TARGET_OPTIONS
| | ARRAY_SIZE ( target_options ) > 1
# endif
)
{
int doc = 0 ;
undoc = 0 ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
printf ( _ ( " \n Target specific options: \n " ) ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
for ( i = ARRAY_SIZE ( target_switches ) ; i - - ; )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
const char * option = target_switches [ i ] . name ;
const char * description = target_switches [ i ] . description ;
if ( option = = NULL | | * option = = 0 )
continue ;
else if ( description = = NULL )
{
undoc = 1 ;
if ( extra_warnings )
printf ( _ ( " -m%-23.23s [undocumented] \n " ) , option ) ;
}
else if ( * description ! = 0 )
doc + = printf ( " -m%-23.23s %s \n " , option , _ ( description ) ) ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
# ifdef TARGET_OPTIONS
for ( i = ARRAY_SIZE ( target_options ) ; i - - ; )
{
const char * option = target_options [ i ] . prefix ;
const char * description = target_options [ i ] . description ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
if ( option = = NULL | | * option = = 0 )
continue ;
else if ( description = = NULL )
{
undoc = 1 ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
if ( extra_warnings )
printf ( _ ( " -m%-23.23s [undocumented] \n " ) , option ) ;
}
else if ( * description ! = 0 )
doc + = printf ( " -m%-23.23s %s \n " , option , _ ( description ) ) ;
}
# endif
if ( undoc )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
if ( doc )
printf ( _ ( " \n There are undocumented target specific options as well. \n " ) ) ;
else
printf ( _ ( " They exist, but they are not documented. \n " ) ) ;
1999-10-27 09:31:52 +00:00
}
1999-08-30 04:01:02 +00:00
}
2002-02-06 04:59:39 +00:00
}
/* Parse a -d... command line switch. */
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
static void
decode_d_option ( arg )
const char * arg ;
{
int i , c , matched ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
while ( * arg )
switch ( c = * arg + + )
{
case ' a ' :
for ( i = 0 ; i < ( int ) DFI_MAX ; + + i )
dump_file [ i ] . enabled = 1 ;
break ;
case ' A ' :
flag_debug_asm = 1 ;
break ;
case ' p ' :
flag_print_asm_name = 1 ;
break ;
case ' P ' :
flag_dump_rtl_in_asm = 1 ;
flag_print_asm_name = 1 ;
break ;
case ' v ' :
graph_dump_format = vcg ;
break ;
case ' x ' :
rtl_dump_and_exit = 1 ;
break ;
case ' y ' :
( * lang_hooks . set_yydebug ) ( 1 ) ;
break ;
case ' D ' : /* These are handled by the preprocessor. */
case ' I ' :
break ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
default :
matched = 0 ;
for ( i = 0 ; i < ( int ) DFI_MAX ; + + i )
if ( c = = dump_file [ i ] . debug_switch )
{
dump_file [ i ] . enabled = 1 ;
matched = 1 ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( ! matched )
warning ( " unrecognized gcc debugging option: %c " , c ) ;
break ;
}
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Parse a -f... command line switch. ARG is the value after the -f.
It is safe to access ' ARG - 2 ' to generate the full switch name .
Return the number of strings consumed . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
static int
decode_f_option ( arg )
const char * arg ;
{
int j ;
const char * option_value = NULL ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Search for the option in the table of binary f options. */
for ( j = ARRAY_SIZE ( f_options ) ; j - - ; )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
if ( ! strcmp ( arg , f_options [ j ] . string ) )
{
* f_options [ j ] . variable = f_options [ j ] . on_value ;
return 1 ;
}
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
if ( arg [ 0 ] = = ' n ' & & arg [ 1 ] = = ' o ' & & arg [ 2 ] = = ' - '
& & ! strcmp ( arg + 3 , f_options [ j ] . string ) )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
* f_options [ j ] . variable = ! f_options [ j ] . on_value ;
return 1 ;
1996-09-18 05:35:50 +00:00
}
}
2002-02-06 04:59:39 +00:00
if ( ! strcmp ( arg , " fast-math " ) )
set_fast_math_flags ( ) ;
else if ( ! strcmp ( arg , " no-fast-math " ) )
set_no_fast_math_flags ( ) ;
else if ( ( option_value = skip_leading_substring ( arg , " inline-limit- " ) )
| | ( option_value = skip_leading_substring ( arg , " inline-limit= " ) ) )
{
int val =
read_integral_parameter ( option_value , arg - 2 ,
MAX_INLINE_INSNS ) ;
set_param_value ( " max-inline-insns " , val ) ;
}
# ifdef INSN_SCHEDULING
else if ( ( option_value = skip_leading_substring ( arg , " sched-verbose= " ) ) )
fix_sched_param ( " verbose " , option_value ) ;
# endif
else if ( ( option_value = skip_leading_substring ( arg , " fixed- " ) ) )
fix_register ( option_value , 1 , 1 ) ;
else if ( ( option_value = skip_leading_substring ( arg , " call-used- " ) ) )
fix_register ( option_value , 0 , 1 ) ;
else if ( ( option_value = skip_leading_substring ( arg , " call-saved- " ) ) )
fix_register ( option_value , 0 , 0 ) ;
else if ( ( option_value = skip_leading_substring ( arg , " align-loops= " ) ) )
align_loops = read_integral_parameter ( option_value , arg - 2 , align_loops ) ;
else if ( ( option_value = skip_leading_substring ( arg , " align-functions= " ) ) )
align_functions
= read_integral_parameter ( option_value , arg - 2 , align_functions ) ;
else if ( ( option_value = skip_leading_substring ( arg , " align-jumps= " ) ) )
align_jumps = read_integral_parameter ( option_value , arg - 2 , align_jumps ) ;
else if ( ( option_value = skip_leading_substring ( arg , " align-labels= " ) ) )
align_labels
= read_integral_parameter ( option_value , arg - 2 , align_labels ) ;
else if ( ( option_value
= skip_leading_substring ( arg , " stack-limit-register= " ) ) )
{
int reg = decode_reg_name ( option_value ) ;
if ( reg < 0 )
error ( " unrecognized register name `%s' " , option_value ) ;
else
stack_limit_rtx = gen_rtx_REG ( Pmode , reg ) ;
}
else if ( ( option_value
= skip_leading_substring ( arg , " stack-limit-symbol= " ) ) )
{
const char * nm ;
nm = ggc_strdup ( option_value ) ;
stack_limit_rtx = gen_rtx_SYMBOL_REF ( Pmode , nm ) ;
}
else if ( ( option_value
= skip_leading_substring ( arg , " message-length= " ) ) )
output_set_maximum_length
( & global_dc - > buffer , read_integral_parameter
( option_value , arg - 2 , diagnostic_line_cutoff ( global_dc ) ) ) ;
else if ( ( option_value
= skip_leading_substring ( arg , " diagnostics-show-location= " ) ) )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
if ( ! strcmp ( option_value , " once " ) )
diagnostic_prefixing_rule ( global_dc ) = DIAGNOSTICS_SHOW_PREFIX_ONCE ;
else if ( ! strcmp ( option_value , " every-line " ) )
diagnostic_prefixing_rule ( global_dc )
= DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE ;
else
error ( " unrecognized option `%s' " , arg - 2 ) ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
else if ( ! strcmp ( arg , " no-stack-limit " ) )
stack_limit_rtx = NULL_RTX ;
else if ( ! strcmp ( arg , " preprocessed " ) )
/* Recognise this switch but do nothing. This prevents warnings
about an unrecognized switch if cpplib has not been linked in . */
;
else
return 0 ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
return 1 ;
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
/* Parse a -W... command line switch. ARG is the value after the -W.
It is safe to access ' ARG - 2 ' to generate the full switch name .
Return the number of strings consumed . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
static int
decode_W_option ( arg )
const char * arg ;
{
const char * option_value = NULL ;
int j ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
/* Search for the option in the table of binary W options. */
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
for ( j = ARRAY_SIZE ( W_options ) ; j - - ; )
{
if ( ! strcmp ( arg , W_options [ j ] . string ) )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
* W_options [ j ] . variable = W_options [ j ] . on_value ;
return 1 ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
if ( arg [ 0 ] = = ' n ' & & arg [ 1 ] = = ' o ' & & arg [ 2 ] = = ' - '
& & ! strcmp ( arg + 3 , W_options [ j ] . string ) )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
* W_options [ j ] . variable = ! W_options [ j ] . on_value ;
return 1 ;
1999-10-27 09:31:52 +00:00
}
1999-08-30 04:01:02 +00:00
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( ( option_value = skip_leading_substring ( arg , " id-clash- " ) ) )
warning ( " -Wid-clash-LEN is no longer supported " ) ;
else if ( ( option_value = skip_leading_substring ( arg , " larger-than- " ) ) )
{
larger_than_size = read_integral_parameter ( option_value , arg - 2 , - 1 ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
warn_larger_than = larger_than_size ! = - 1 ;
}
else if ( ! strcmp ( arg , " unused " ) )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
set_Wunused ( 1 ) ;
}
else if ( ! strcmp ( arg , " no-unused " ) )
{
set_Wunused ( 0 ) ;
}
else
return 0 ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
return 1 ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Parse a -g... command line switch. ARG is the value after the -g.
It is safe to access ' ARG - 2 ' to generate the full switch name .
Return the number of strings consumed . */
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
static int
decode_g_option ( arg )
const char * arg ;
{
static unsigned level = 0 ;
/* A lot of code assumes write_symbols == NO_DEBUG if the
debugging level is 0 ( thus - gstabs1 - gstabs0 would lose track
of what debugging type has been selected ) . This records the
selected type . It is an error to specify more than one
debugging type . */
static enum debug_info_type selected_debug_type = NO_DEBUG ;
/* Non-zero if debugging format has been explicitly set.
- g and - ggdb don ' t explicitly set the debugging format so
- gdwarf - g3 is equivalent to - gdwarf3 . */
static int type_explicitly_set_p = 0 ;
/* Indexed by enum debug_info_type. */
static const char * const debug_type_names [ ] =
{
" none " , " stabs " , " coff " , " dwarf-1 " , " dwarf-2 " , " xcoff " , " vms "
} ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
/* The maximum admissible debug level value. */
static const unsigned max_debug_level = 3 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Look up ARG in the table. */
for ( da = debug_args ; da - > arg ; da + + )
{
const int da_len = strlen ( da - > arg ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
if ( da_len = = 0 | | ! strncmp ( arg , da - > arg , da_len ) )
{
enum debug_info_type type = da - > debug_type ;
const char * p = arg + da_len ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
if ( * p & & ! ISDIGIT ( * p ) )
continue ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* A debug flag without a level defaults to level 2.
Note we do not want to call read_integral_parameter
for that case since it will call atoi which
will return zero .
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
? ? ? We may want to generalize the interface to
read_integral_parameter to better handle this case
if this case shows up often . */
if ( * p )
level = read_integral_parameter ( p , 0 , max_debug_level + 1 ) ;
else
level = ( level = = 0 ) ? 2 : level ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( da_len > 1 & & * p & & ! strncmp ( arg , " dwarf " , da_len ) )
{
error ( " use -gdwarf -g%d for DWARF v1, level %d " ,
level , level ) ;
if ( level = = 2 )
error ( " use -gdwarf-2 for DWARF v2 " ) ;
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
if ( level > max_debug_level )
{
warning ( " \
ignoring option ` % s ' due to invalid debug level specification " ,
arg - 2 ) ;
level = debug_info_level ;
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
if ( type = = NO_DEBUG )
{
type = PREFERRED_DEBUGGING_TYPE ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( da_len > 1 & & strncmp ( arg , " gdb " , da_len ) = = 0 )
{
2002-05-09 22:15:04 +00:00
# ifdef DWARF2_DEBUGGING_INFO
2002-02-06 04:59:39 +00:00
type = DWARF2_DEBUG ;
# else
# ifdef DBX_DEBUGGING_INFO
type = DBX_DEBUG ;
# endif
# endif
}
}
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
if ( type = = NO_DEBUG )
warning ( " `%s': unknown or unsupported -g option " , arg - 2 ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Does it conflict with an already selected type? */
if ( type_explicitly_set_p
/* -g/-ggdb don't conflict with anything. */
& & da - > debug_type ! = NO_DEBUG
& & type ! = selected_debug_type )
warning ( " `%s' ignored, conflicts with `-g%s' " ,
arg - 2 , debug_type_names [ ( int ) selected_debug_type ] ) ;
else
{
/* If the format has already been set, -g/-ggdb
only change the debug level . */
if ( type_explicitly_set_p & & da - > debug_type = = NO_DEBUG )
/* Don't change debugging type. */
;
else
{
selected_debug_type = type ;
type_explicitly_set_p = da - > debug_type ! = NO_DEBUG ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
write_symbols = ( level = = 0
? NO_DEBUG
: selected_debug_type ) ;
use_gnu_debug_info_extensions = da - > use_extensions_p ;
debug_info_level = ( enum debug_info_level ) level ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
break ;
}
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( ! da - > arg )
return 0 ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
return 1 ;
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
/* Decode the first argument in the argv as a language-independent option.
Return the number of strings consumed . */
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
static unsigned int
independent_decode_option ( argc , argv )
int argc ;
char * * argv ;
{
char * arg = argv [ 0 ] ;
if ( arg [ 0 ] ! = ' - ' | | arg [ 1 ] = = 0 )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
if ( arg [ 0 ] = = ' + ' )
return 0 ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
filename = arg ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
return 1 ;
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
arg + + ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
if ( ! strcmp ( arg , " -help " ) )
{
display_help ( ) ;
exit_after_options = 1 ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
if ( ! strcmp ( arg , " -target-help " ) )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
display_target_options ( ) ;
exit_after_options = 1 ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
if ( ! strcmp ( arg , " -version " ) )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
print_version ( stderr , " " ) ;
exit_after_options = 1 ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
/* Handle '--param <name>=<value>'. */
if ( strcmp ( arg , " -param " ) = = 0 )
{
char * equal ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
if ( argc = = 1 )
{
error ( " -param option missing argument " ) ;
return 1 ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Get the '<name>=<value>' parameter. */
arg = argv [ 1 ] ;
/* Look for the `='. */
equal = strchr ( arg , ' = ' ) ;
if ( ! equal )
error ( " invalid --param option: %s " , arg ) ;
else
{
int val ;
/* Zero out the `=' sign so that we get two separate strings. */
* equal = ' \0 ' ;
/* Figure out what value is specified. */
val = read_integral_parameter ( equal + 1 , NULL , INVALID_PARAM_VAL ) ;
if ( val ! = INVALID_PARAM_VAL )
set_param_value ( arg , val ) ;
else
error ( " invalid parameter value `%s' " , equal + 1 ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
return 2 ;
1999-08-30 04:01:02 +00:00
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
if ( * arg = = ' Y ' )
arg + + ;
switch ( * arg )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
default :
return 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
case ' O ' :
/* Already been treated in main (). Do nothing. */
break ;
case ' m ' :
set_target_switch ( arg + 1 ) ;
break ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
case ' f ' :
return decode_f_option ( arg + 1 ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
case ' g ' :
return decode_g_option ( arg + 1 ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
case ' d ' :
if ( ! strcmp ( arg , " dumpbase " ) )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
if ( argc = = 1 )
return 0 ;
dump_base_name = argv [ 1 ] ;
return 2 ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
else
decode_d_option ( arg + 1 ) ;
break ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
case ' p ' :
if ( ! strcmp ( arg , " pedantic " ) )
pedantic = 1 ;
else if ( ! strcmp ( arg , " pedantic-errors " ) )
flag_pedantic_errors = pedantic = 1 ;
else if ( arg [ 1 ] = = 0 )
profile_flag = 1 ;
else
return 0 ;
break ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
case ' q ' :
if ( ! strcmp ( arg , " quiet " ) )
quiet_flag = 1 ;
else
return 0 ;
break ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
case ' v ' :
if ( ! strcmp ( arg , " version " ) )
version_flag = 1 ;
else
return 0 ;
break ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
case ' w ' :
if ( arg [ 1 ] = = 0 )
inhibit_warnings = 1 ;
else
return 0 ;
break ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
case ' W ' :
if ( arg [ 1 ] = = 0 )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
extra_warnings = 1 ;
/* We save the value of warn_uninitialized, since if they put
- Wuninitialized on the command line , we need to generate a
warning about not using it without also specifying - O . */
if ( warn_uninitialized ! = 1 )
warn_uninitialized = 2 ;
1999-10-27 09:31:52 +00:00
}
2002-02-06 04:59:39 +00:00
else
return decode_W_option ( arg + 1 ) ;
break ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
case ' a ' :
if ( ! strncmp ( arg , " aux-info " , 8 ) )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
if ( arg [ 8 ] = = ' \0 ' )
{
if ( argc = = 1 )
return 0 ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
aux_info_file_name = argv [ 1 ] ;
flag_gen_aux_info = 1 ;
return 2 ;
}
else if ( arg [ 8 ] = = ' = ' )
{
aux_info_file_name = arg + 9 ;
flag_gen_aux_info = 1 ;
}
else
return 0 ;
}
else
return 0 ;
break ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
case ' o ' :
if ( arg [ 1 ] = = 0 )
{
if ( argc = = 1 )
return 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
asm_file_name = argv [ 1 ] ;
return 2 ;
}
return 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
case ' G ' :
{
int g_switch_val ;
int return_val ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( arg [ 1 ] = = 0 )
{
if ( argc = = 1 )
return 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
g_switch_val = read_integral_parameter ( argv [ 1 ] , 0 , - 1 ) ;
return_val = 2 ;
}
else
{
g_switch_val = read_integral_parameter ( arg + 1 , 0 , - 1 ) ;
return_val = 1 ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( g_switch_val = = - 1 )
return_val = 0 ;
else
{
g_switch_set = TRUE ;
g_switch_value = g_switch_val ;
}
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
return return_val ;
}
}
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
return 1 ;
}
/* Decode -m switches. */
/* Decode the switch -mNAME. */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
static void
set_target_switch ( name )
const char * name ;
{
size_t j ;
int valid_target_option = 0 ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
for ( j = 0 ; j < ARRAY_SIZE ( target_switches ) ; j + + )
if ( ! strcmp ( target_switches [ j ] . name , name ) )
{
if ( target_switches [ j ] . value < 0 )
target_flags & = ~ - target_switches [ j ] . value ;
else
target_flags | = target_switches [ j ] . value ;
valid_target_option = 1 ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
# ifdef TARGET_OPTIONS
if ( ! valid_target_option )
for ( j = 0 ; j < ARRAY_SIZE ( target_options ) ; j + + )
{
int len = strlen ( target_options [ j ] . prefix ) ;
if ( ! strncmp ( target_options [ j ] . prefix , name , len ) )
{
* target_options [ j ] . variable = name + len ;
valid_target_option = 1 ;
}
}
1996-09-18 05:35:50 +00:00
# endif
2002-02-06 04:59:39 +00:00
if ( ! valid_target_option )
error ( " invalid option `%s' " , name ) ;
}
/* Print version information to FILE.
Each line begins with INDENT ( for the case where FILE is the
assembler output file ) . */
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
static void
print_version ( file , indent )
FILE * file ;
const char * indent ;
{
# ifndef __VERSION__
# define __VERSION__ "[?]"
1999-08-30 04:01:02 +00:00
# endif
2002-02-06 04:59:39 +00:00
fnotice ( file ,
# ifdef __GNUC__
" %s%s%s version %s (%s) \n %s \t compiled by GNU C version %s. \n "
# else
" %s%s%s version %s (%s) compiled by CC. \n "
1996-09-18 05:35:50 +00:00
# endif
2002-02-06 04:59:39 +00:00
, indent , * indent ! = 0 ? " " : " " ,
lang_hooks . name , version_string , TARGET_NAME ,
indent , __VERSION__ ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Print an option value and return the adjusted position in the line.
? ? ? We don ' t handle error returns from fprintf ( disk full ) ; presumably
other code will catch a disk full though . */
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
static int
print_single_switch ( file , pos , max , indent , sep , term , type , name )
FILE * file ;
int pos , max ;
const char * indent , * sep , * term , * type , * name ;
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
/* The ultrix fprintf returns 0 on success, so compute the result we want
here since we need it for the following test . */
int len = strlen ( sep ) + strlen ( type ) + strlen ( name ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
if ( pos ! = 0
& & pos + len > max )
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
fprintf ( file , " %s " , term ) ;
pos = 0 ;
1999-08-30 04:01:02 +00:00
}
2002-02-06 04:59:39 +00:00
if ( pos = = 0 )
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
fprintf ( file , " %s " , indent ) ;
pos = strlen ( indent ) ;
1999-08-30 04:01:02 +00:00
}
2002-02-06 04:59:39 +00:00
fprintf ( file , " %s%s%s " , sep , type , name ) ;
pos + = len ;
return pos ;
}
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Print active target switches to FILE.
POS is the current cursor position and MAX is the size of a " line " .
Each line begins with INDENT and ends with TERM .
Each switch is separated from the next by SEP . */
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
static void
print_switch_values ( file , pos , max , indent , sep , term )
FILE * file ;
int pos , max ;
const char * indent , * sep , * term ;
{
size_t j ;
char * * p ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Print the options as passed. */
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
pos = print_single_switch ( file , pos , max , indent , * indent ? " " : " " , term ,
_ ( " options passed: " ) , " " ) ;
for ( p = & save_argv [ 1 ] ; * p ! = NULL ; p + + )
if ( * * p = = ' - ' )
{
/* Ignore these. */
if ( strcmp ( * p , " -o " ) = = 0 )
{
if ( p [ 1 ] ! = NULL )
p + + ;
1999-08-30 04:01:02 +00:00
continue ;
2002-02-06 04:59:39 +00:00
}
if ( strcmp ( * p , " -quiet " ) = = 0 )
continue ;
if ( strcmp ( * p , " -version " ) = = 0 )
continue ;
if ( ( * p ) [ 1 ] = = ' d ' )
continue ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
pos = print_single_switch ( file , pos , max , indent , sep , term , * p , " " ) ;
}
if ( pos > 0 )
fprintf ( file , " %s " , term ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Print the -f and -m options that have been enabled.
We don ' t handle language specific options but printing argv
should suffice . */
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
pos = print_single_switch ( file , 0 , max , indent , * indent ? " " : " " , term ,
_ ( " options enabled: " ) , " " ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
for ( j = 0 ; j < ARRAY_SIZE ( f_options ) ; j + + )
if ( * f_options [ j ] . variable = = f_options [ j ] . on_value )
pos = print_single_switch ( file , pos , max , indent , sep , term ,
" -f " , f_options [ j ] . string ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Print target specific options. */
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
for ( j = 0 ; j < ARRAY_SIZE ( target_switches ) ; j + + )
if ( target_switches [ j ] . name [ 0 ] ! = ' \0 '
& & target_switches [ j ] . value > 0
& & ( ( target_switches [ j ] . value & target_flags )
= = target_switches [ j ] . value ) )
{
pos = print_single_switch ( file , pos , max , indent , sep , term ,
" -m " , target_switches [ j ] . name ) ;
}
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
# ifdef TARGET_OPTIONS
for ( j = 0 ; j < ARRAY_SIZE ( target_options ) ; j + + )
if ( * target_options [ j ] . variable ! = NULL )
{
char prefix [ 256 ] ;
sprintf ( prefix , " -m%s " , target_options [ j ] . prefix ) ;
pos = print_single_switch ( file , pos , max , indent , sep , term ,
prefix , * target_options [ j ] . variable ) ;
}
# endif
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
fprintf ( file , " %s " , term ) ;
}
/* Open assembly code output file. Do this even if -fsyntax-only is
on , because then the driver will have provided the name of a
temporary file or bit bucket for us . NAME is the file specified on
the command line , possibly NULL . */
static void
init_asm_output ( name )
const char * name ;
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
if ( name = = NULL & & asm_file_name = = 0 )
asm_out_file = stdout ;
1999-10-27 09:31:52 +00:00
else
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
if ( asm_file_name = = 0 )
{
int len = strlen ( dump_base_name ) ;
char * dumpname = ( char * ) xmalloc ( len + 6 ) ;
memcpy ( dumpname , dump_base_name , len + 1 ) ;
strip_off_ending ( dumpname , len ) ;
strcat ( dumpname , " .s " ) ;
asm_file_name = dumpname ;
}
if ( ! strcmp ( asm_file_name , " - " ) )
asm_out_file = stdout ;
else
asm_out_file = fopen ( asm_file_name , " w " ) ;
if ( asm_out_file = = 0 )
fatal_io_error ( " can't open %s for writing " , asm_file_name ) ;
1999-08-30 04:01:02 +00:00
}
2002-02-06 04:59:39 +00:00
# ifdef IO_BUFFER_SIZE
setvbuf ( asm_out_file , ( char * ) xmalloc ( IO_BUFFER_SIZE ) ,
_IOFBF , IO_BUFFER_SIZE ) ;
# endif
if ( ! flag_syntax_only )
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
# ifdef ASM_FILE_START
ASM_FILE_START ( asm_out_file ) ;
# endif
# ifdef ASM_COMMENT_START
if ( flag_verbose_asm )
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
/* Print the list of options in effect. */
print_version ( asm_out_file , ASM_COMMENT_START ) ;
print_switch_values ( asm_out_file , 0 , MAX_LINE ,
ASM_COMMENT_START , " " , " \n " ) ;
/* Add a blank line here so it appears in assembler output but not
screen output . */
fprintf ( asm_out_file , " \n " ) ;
1999-08-30 04:01:02 +00:00
}
2002-02-06 04:59:39 +00:00
# endif
1999-08-30 04:01:02 +00:00
}
}
2002-02-06 04:59:39 +00:00
/* Initialization of the front end environment, before command line
options are parsed . Signal handlers , internationalization etc .
ARGV0 is main ' s argv [ 0 ] . */
static void
general_init ( argv0 )
char * argv0 ;
1996-09-18 05:35:50 +00:00
{
char * p ;
2002-02-06 04:59:39 +00:00
p = argv0 + strlen ( argv0 ) ;
while ( p ! = argv0 & & ! IS_DIR_SEPARATOR ( p [ - 1 ] ) )
1996-09-18 05:35:50 +00:00
- - p ;
progname = p ;
2002-02-06 04:59:39 +00:00
xmalloc_set_program_name ( progname ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
gcc_init_libintl ( ) ;
1999-10-27 09:31:52 +00:00
2002-02-06 04:59:39 +00:00
/* Install handler for SIGFPE, which may be received while we do
compile - time floating point arithmetic . */
1996-09-18 05:35:50 +00:00
signal ( SIGFPE , float_signal ) ;
2002-02-06 04:59:39 +00:00
/* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages. */
# ifdef SIGSEGV
signal ( SIGSEGV , crash_signal ) ;
# endif
# ifdef SIGILL
signal ( SIGILL , crash_signal ) ;
# endif
# ifdef SIGBUS
signal ( SIGBUS , crash_signal ) ;
# endif
# ifdef SIGABRT
signal ( SIGABRT , crash_signal ) ;
# endif
# if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT)
signal ( SIGIOT , crash_signal ) ;
1996-09-18 05:35:50 +00:00
# endif
2002-02-06 04:59:39 +00:00
/* Initialize the diagnostics reporting machinery, so option parsing
can give warnings and errors . */
diagnostic_initialize ( global_dc ) ;
}
/* Parse command line options and set default flag values, called
after language - independent option - independent initialization . Do
minimal options processing . Outputting diagnostics is OK , but GC
and identifier hashtables etc . are not initialized yet . */
static void
parse_options_and_default_flags ( argc , argv )
int argc ;
char * * argv ;
{
int i ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Save in case md file wants to emit args as a comment. */
save_argc = argc ;
save_argv = argv ;
/* Initialize register usage now so switches may override. */
init_reg_sets ( ) ;
/* Register the language-independent parameters. */
add_params ( lang_independent_params , LAST_PARAM ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Perform language-specific options initialization. */
( * lang_hooks . init_options ) ( ) ;
1999-08-30 04:01:02 +00:00
1996-09-18 05:35:50 +00:00
/* Scan to see what optimization level has been specified. That will
determine the default value of many flags . */
for ( i = 1 ; i < argc ; i + + )
{
if ( ! strcmp ( argv [ i ] , " -O " ) )
{
optimize = 1 ;
1999-10-27 09:31:52 +00:00
optimize_size = 0 ;
1996-09-18 05:35:50 +00:00
}
else if ( argv [ i ] [ 0 ] = = ' - ' & & argv [ i ] [ 1 ] = = ' O ' )
{
1999-08-30 04:01:02 +00:00
/* Handle -Os, -O2, -O3, -O69, ... */
1996-09-18 05:35:50 +00:00
char * p = & argv [ i ] [ 2 ] ;
2002-02-06 04:59:39 +00:00
1999-08-30 04:01:02 +00:00
if ( ( p [ 0 ] = = ' s ' ) & & ( p [ 1 ] = = 0 ) )
1999-10-27 09:31:52 +00:00
{
optimize_size = 1 ;
2002-02-06 04:59:39 +00:00
/* Optimizing for size forces optimize to be 2. */
1999-10-27 09:31:52 +00:00
optimize = 2 ;
}
1999-08-30 04:01:02 +00:00
else
2002-02-06 04:59:39 +00:00
{
1999-10-27 09:31:52 +00:00
const int optimize_val = read_integral_parameter ( p , p - 2 , - 1 ) ;
if ( optimize_val ! = - 1 )
{
optimize = optimize_val ;
2002-02-06 04:59:39 +00:00
2001-08-16 06:05:18 +00:00
# ifdef FORCE_OPTIMIZATION_DOWNGRADE
# warning FORCE_OPTIMIZATION_DOWNGRADE
if ( optimize > FORCE_OPTIMIZATION_DOWNGRADE )
{
optimize = FORCE_OPTIMIZATION_DOWNGRADE ;
2002-05-09 22:15:04 +00:00
warning ( " \n *** \n *** \t -O%d converted to \" -O%d \" due to optimizer bugs on this platform \n *** " ,
2001-08-16 06:05:18 +00:00
optimize_val ,
FORCE_OPTIMIZATION_DOWNGRADE ) ;
}
# endif /*FORCE_OPTIMIZATION_DOWNGRADE*/
2002-02-06 04:59:39 +00:00
2002-09-22 07:26:38 +00:00
# if defined(TRY_WITHOUT_THIS__alpha__)
2000-03-26 12:56:54 +00:00
if ( optimize > 1 )
{
2002-05-09 22:15:04 +00:00
warning ( " \n *** \n *** \t The -O%d flag TRIGGERS KNOWN OPTIMIZER BUGS ON THIS PLATFORM \n *** " ,
2000-03-26 12:56:54 +00:00
optimize_val ) ;
}
2000-12-01 10:20:17 +00:00
# endif /*__alpha__*/
2002-02-06 04:59:39 +00:00
1999-10-27 09:31:52 +00:00
optimize_size = 0 ;
}
1999-08-30 04:01:02 +00:00
}
1996-09-18 05:35:50 +00:00
}
}
2002-02-06 04:59:39 +00:00
if ( ! optimize )
{
flag_merge_constants = 0 ;
}
1996-09-18 05:35:50 +00:00
if ( optimize > = 1 )
{
flag_defer_pop = 1 ;
flag_thread_jumps = 1 ;
# ifdef DELAY_SLOTS
flag_delayed_branch = 1 ;
# endif
# ifdef CAN_DEBUG_WITHOUT_FP
flag_omit_frame_pointer = 1 ;
# endif
2002-02-06 04:59:39 +00:00
flag_guess_branch_prob = 1 ;
flag_cprop_registers = 1 ;
1996-09-18 05:35:50 +00:00
}
if ( optimize > = 2 )
{
2002-02-06 04:59:39 +00:00
flag_optimize_sibling_calls = 1 ;
1996-09-18 05:35:50 +00:00
flag_cse_follow_jumps = 1 ;
flag_cse_skip_blocks = 1 ;
1999-08-30 04:01:02 +00:00
flag_gcse = 1 ;
1996-09-18 05:35:50 +00:00
flag_expensive_optimizations = 1 ;
flag_strength_reduce = 1 ;
flag_rerun_cse_after_loop = 1 ;
1999-08-30 04:01:02 +00:00
flag_rerun_loop_opt = 1 ;
1996-09-18 05:35:50 +00:00
flag_caller_saves = 1 ;
flag_force_mem = 1 ;
2002-02-06 04:59:39 +00:00
flag_peephole2 = 1 ;
1996-09-18 05:35:50 +00:00
# ifdef INSN_SCHEDULING
flag_schedule_insns = 1 ;
flag_schedule_insns_after_reload = 1 ;
# endif
1999-08-30 04:01:02 +00:00
flag_regmove = 1 ;
2002-02-06 04:59:39 +00:00
flag_strict_aliasing = 1 ;
flag_delete_null_pointer_checks = 1 ;
flag_reorder_blocks = 1 ;
1996-09-18 05:35:50 +00:00
}
if ( optimize > = 3 )
{
flag_inline_functions = 1 ;
2002-02-06 04:59:39 +00:00
flag_rename_registers = 1 ;
}
2002-06-21 18:21:30 +00:00
if ( optimize_size )
2002-02-06 04:59:39 +00:00
{
align_loops = 1 ;
align_jumps = 1 ;
align_labels = 1 ;
align_functions = 1 ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Initialize whether `char' is signed. */
flag_signed_char = DEFAULT_SIGNED_CHAR ;
# ifdef DEFAULT_SHORT_ENUMS
/* Initialize how much space enums occupy, by default. */
flag_short_enums = DEFAULT_SHORT_ENUMS ;
# endif
1999-08-30 04:01:02 +00:00
/* Initialize target_flags before OPTIMIZATION_OPTIONS so the latter can
modify it . */
target_flags = 0 ;
set_target_switch ( " " ) ;
2002-02-06 04:59:39 +00:00
/* Unwind tables are always present in an ABI-conformant IA-64
object file , so the default should be ON . */
# ifdef IA64_UNWIND_INFO
flag_unwind_tables = IA64_UNWIND_INFO ;
# endif
1996-09-18 05:35:50 +00:00
# ifdef OPTIMIZATION_OPTIONS
/* Allow default optimizations to be specified on a per-machine basis. */
1999-08-30 04:01:02 +00:00
OPTIMIZATION_OPTIONS ( optimize , optimize_size ) ;
1996-09-18 05:35:50 +00:00
# endif
2002-02-06 04:59:39 +00:00
/* Perform normal command line switch decoding. */
for ( i = 1 ; i < argc ; )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
int lang_processed ;
int indep_processed ;
/* Give the language a chance to decode the option for itself. */
lang_processed = ( * lang_hooks . decode_option ) ( argc - i , argv + i ) ;
if ( lang_processed > = 0 )
/* Now see if the option also has a language independent meaning.
Some options are both language specific and language independent ,
eg - - help . */
indep_processed = independent_decode_option ( argc - i , argv + i ) ;
else
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
lang_processed = - lang_processed ;
indep_processed = 0 ;
1999-08-30 04:01:02 +00:00
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( lang_processed | | indep_processed )
i + = MAX ( lang_processed , indep_processed ) ;
else
{
const char * option = NULL ;
const char * lang = NULL ;
unsigned int j ;
/* It is possible that the command line switch is not valid for the
current language , but it is valid for another language . In order
to be compatible with previous versions of the compiler ( which
did not issue an error message in this case ) we check for this
possibility here . If we do find a match , then if extra_warnings
is set we generate a warning message , otherwise we will just
ignore the option . */
for ( j = 0 ; j < ARRAY_SIZE ( documented_lang_options ) ; j + + )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
option = documented_lang_options [ j ] . option ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
if ( option = = NULL )
lang = documented_lang_options [ j ] . description ;
else if ( ! strncmp ( argv [ i ] , option , strlen ( option ) ) )
break ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
if ( j ! = ARRAY_SIZE ( documented_lang_options ) )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
if ( extra_warnings )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
warning ( " ignoring command line option '%s' " , argv [ i ] ) ;
if ( lang )
warning
( " (it is valid for %s but not the selected language) " ,
lang ) ;
1999-10-27 09:31:52 +00:00
}
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
else if ( argv [ i ] [ 0 ] = = ' - ' & & argv [ i ] [ 1 ] = = ' g ' )
warning ( " `%s': unknown or unsupported -g option " , & argv [ i ] [ 2 ] ) ;
1996-09-18 05:35:50 +00:00
else
2002-02-06 04:59:39 +00:00
error ( " unrecognized option `%s' " , argv [ i ] ) ;
i + + ;
1996-09-18 05:35:50 +00:00
}
}
2002-05-09 22:15:04 +00:00
if ( flag_no_inline = = 2 )
flag_no_inline = 0 ;
else
flag_really_no_inline = flag_no_inline ;
2002-02-06 04:59:39 +00:00
/* Set flag_no_inline before the post_options () hook. The C front
ends use it to determine tree inlining defaults . FIXME : such
code should be lang - independent when all front ends use tree
inlining , in which case it , and this condition , should be moved
to the top of process_options ( ) instead . */
1996-09-18 05:35:50 +00:00
if ( optimize = = 0 )
{
/* Inlining does not work if not optimizing,
so force it not to be done . */
flag_no_inline = 1 ;
warn_inline = 0 ;
2002-02-06 04:59:39 +00:00
/* The c_decode_option function and decode_option hook set
1996-09-18 05:35:50 +00:00
this to ` 2 ' if - Wall is used , so we can avoid giving out
lots of errors for people who don ' t realize what - Wall does . */
if ( warn_uninitialized = = 1 )
warning ( " -Wuninitialized is not supported without -O " ) ;
}
2002-05-09 22:15:04 +00:00
if ( flag_really_no_inline = = 2 )
flag_really_no_inline = flag_no_inline ;
2002-02-06 04:59:39 +00:00
/* All command line options have been parsed; allow the front end to
perform consistency checks , etc . */
( * lang_hooks . post_options ) ( ) ;
}
/* Process the options that have been parsed. */
static void
process_options ( )
{
1996-09-18 05:35:50 +00:00
# ifdef OVERRIDE_OPTIONS
/* Some machines may reject certain combinations of options. */
OVERRIDE_OPTIONS ;
# endif
2002-02-06 04:59:39 +00:00
/* Set up the align_*_log variables, defaulting them to 1 if they
were still unset . */
if ( align_loops < = 0 ) align_loops = 1 ;
if ( align_loops_max_skip > align_loops | | ! align_loops )
align_loops_max_skip = align_loops - 1 ;
align_loops_log = floor_log2 ( align_loops * 2 - 1 ) ;
if ( align_jumps < = 0 ) align_jumps = 1 ;
if ( align_jumps_max_skip > align_jumps | | ! align_jumps )
align_jumps_max_skip = align_jumps - 1 ;
align_jumps_log = floor_log2 ( align_jumps * 2 - 1 ) ;
if ( align_labels < = 0 ) align_labels = 1 ;
align_labels_log = floor_log2 ( align_labels * 2 - 1 ) ;
if ( align_labels_max_skip > align_labels | | ! align_labels )
align_labels_max_skip = align_labels - 1 ;
if ( align_functions < = 0 ) align_functions = 1 ;
align_functions_log = floor_log2 ( align_functions * 2 - 1 ) ;
1999-08-30 04:01:02 +00:00
1996-09-18 05:35:50 +00:00
/* Unrolling all loops implies that standard loop unrolling must also
be done . */
if ( flag_unroll_all_loops )
flag_unroll_loops = 1 ;
/* Loop unrolling requires that strength_reduction be on also. Silently
turn on strength reduction here if it isn ' t already on . Also , the loop
unrolling code assumes that cse will be run after loop , so that must
be turned on also . */
if ( flag_unroll_loops )
{
flag_strength_reduce = 1 ;
flag_rerun_cse_after_loop = 1 ;
}
2002-02-06 04:59:39 +00:00
if ( flag_non_call_exceptions )
flag_asynchronous_unwind_tables = 1 ;
if ( flag_asynchronous_unwind_tables )
flag_unwind_tables = 1 ;
1996-09-18 05:35:50 +00:00
/* Warn about options that are not supported on this machine. */
# ifndef INSN_SCHEDULING
if ( flag_schedule_insns | | flag_schedule_insns_after_reload )
warning ( " instruction scheduling not supported on this target machine " ) ;
# endif
# ifndef DELAY_SLOTS
if ( flag_delayed_branch )
warning ( " this target machine does not have delayed branches " ) ;
# endif
2002-02-06 04:59:39 +00:00
/* Some operating systems do not allow profiling without a frame
pointer . */
if ( ! TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
& & profile_flag
& & flag_omit_frame_pointer )
{
error ( " profiling does not work without a frame pointer " ) ;
flag_omit_frame_pointer = 0 ;
}
user_label_prefix = USER_LABEL_PREFIX ;
if ( flag_leading_underscore ! = - 1 )
{
/* If the default prefix is more complicated than "" or "_",
issue a warning and ignore this option . */
if ( user_label_prefix [ 0 ] = = 0 | |
( user_label_prefix [ 0 ] = = ' _ ' & & user_label_prefix [ 1 ] = = 0 ) )
{
user_label_prefix = flag_leading_underscore ? " _ " : " " ;
}
else
warning ( " -f%sleading-underscore not supported on this target machine " ,
flag_leading_underscore ? " " : " no- " ) ;
}
/* If we are in verbose mode, write out the version and maybe all the
option flags in use . */
if ( version_flag )
{
print_version ( stderr , " " ) ;
if ( ! quiet_flag )
print_switch_values ( stderr , 0 , MAX_LINE , " " , " " , " \n " ) ;
}
if ( ! quiet_flag )
time_report = 1 ;
if ( flag_syntax_only )
{
write_symbols = NO_DEBUG ;
profile_flag = 0 ;
}
/* Now we know write_symbols, set up the debug hooks based on it.
By default we do nothing for debug output . */
# if defined(DBX_DEBUGGING_INFO)
if ( write_symbols = = DBX_DEBUG )
debug_hooks = & dbx_debug_hooks ;
# endif
# if defined(XCOFF_DEBUGGING_INFO)
if ( write_symbols = = XCOFF_DEBUG )
debug_hooks = & xcoff_debug_hooks ;
# endif
# ifdef SDB_DEBUGGING_INFO
if ( write_symbols = = SDB_DEBUG )
debug_hooks = & sdb_debug_hooks ;
# endif
# ifdef DWARF_DEBUGGING_INFO
if ( write_symbols = = DWARF_DEBUG )
debug_hooks = & dwarf_debug_hooks ;
# endif
# ifdef DWARF2_DEBUGGING_INFO
if ( write_symbols = = DWARF2_DEBUG )
debug_hooks = & dwarf2_debug_hooks ;
# endif
# ifdef VMS_DEBUGGING_INFO
if ( write_symbols = = VMS_DEBUG | | write_symbols = = VMS_AND_DWARF2_DEBUG )
debug_hooks = & vmsdbg_debug_hooks ;
# endif
/* If auxiliary info generation is desired, open the output file.
This goes in the same directory as the source file - - unlike
all the other output files . */
if ( flag_gen_aux_info )
{
aux_info_file = fopen ( aux_info_file_name , " w " ) ;
if ( aux_info_file = = 0 )
fatal_io_error ( " can't open %s " , aux_info_file_name ) ;
}
if ( ! targetm . have_named_sections )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
if ( flag_function_sections )
1999-10-27 09:31:52 +00:00
{
2002-02-06 04:59:39 +00:00
warning ( " -ffunction-sections not supported for this target " ) ;
flag_function_sections = 0 ;
}
if ( flag_data_sections )
{
warning ( " -fdata-sections not supported for this target " ) ;
flag_data_sections = 0 ;
1999-10-27 09:31:52 +00:00
}
}
2002-02-06 04:59:39 +00:00
if ( flag_function_sections & & profile_flag )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
warning ( " -ffunction-sections disabled; it makes profiling impossible " ) ;
flag_function_sections = 0 ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
# ifndef HAVE_prefetch
if ( flag_prefetch_loop_arrays )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
warning ( " -fprefetch-loop-arrays not supported for this target " ) ;
flag_prefetch_loop_arrays = 0 ;
}
# else
if ( flag_prefetch_loop_arrays & & ! HAVE_prefetch )
{
warning ( " -fprefetch-loop-arrays not supported for this target (try -march switches) " ) ;
flag_prefetch_loop_arrays = 0 ;
}
# endif
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* This combination of options isn't handled for i386 targets and doesn't
make much sense anyway , so don ' t allow it . */
if ( flag_prefetch_loop_arrays & & optimize_size )
{
warning ( " -fprefetch-loop-arrays is not supported with -Os " ) ;
flag_prefetch_loop_arrays = 0 ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
# ifndef OBJECT_FORMAT_ELF
if ( flag_function_sections & & write_symbols ! = NO_DEBUG )
warning ( " -ffunction-sections may affect debugging on some targets " ) ;
1999-08-30 04:01:02 +00:00
# endif
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Language-independent initialization, before language-dependent
initialization . */
1999-10-27 09:31:52 +00:00
static void
2002-02-06 04:59:39 +00:00
lang_independent_init ( )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
decl_printable_name = decl_name ;
lang_expand_expr = ( lang_expand_expr_t ) do_abort ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Set the language-dependent identifier size. */
tree_code_length [ ( int ) IDENTIFIER_NODE ]
= ( ( lang_hooks . identifier_size - sizeof ( struct tree_common )
+ sizeof ( tree ) - 1 ) / sizeof ( tree ) ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Initialize the garbage-collector, and string pools. */
init_ggc ( ) ;
ggc_add_rtx_root ( & stack_limit_rtx , 1 ) ;
ggc_add_tree_root ( & current_function_decl , 1 ) ;
ggc_add_tree_root ( & current_function_func_begin_label , 1 ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
init_stringpool ( ) ;
init_obstacks ( ) ;
init_emit_once ( debug_info_level = = DINFO_LEVEL_NORMAL
| | debug_info_level = = DINFO_LEVEL_VERBOSE
# ifdef VMS_DEBUGGING_INFO
/* Enable line number info for traceback */
| | debug_info_level > DINFO_LEVEL_NONE
# endif
| | flag_test_coverage
| | warn_notreached ) ;
init_regs ( ) ;
init_alias_once ( ) ;
init_stmt ( ) ;
init_loop ( ) ;
init_reload ( ) ;
init_function_once ( ) ;
init_stor_layout_once ( ) ;
init_varasm_once ( ) ;
init_EXPR_INSN_LIST_cache ( ) ;
/* The following initialization functions need to generate rtl, so
provide a dummy function context for them . */
init_dummy_function_start ( ) ;
init_expmed ( ) ;
init_expr_once ( ) ;
if ( flag_caller_saves )
init_caller_save ( ) ;
expand_dummy_function_end ( ) ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Language-dependent initialization. Returns non-zero on success. */
static int
lang_dependent_init ( name )
const char * name ;
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
if ( dump_base_name = = 0 )
dump_base_name = name ? name : " gccdump " ;
/* Front-end initialization. This hook can assume that GC,
identifier hashes etc . are set up , but debug initialization is
not done yet . This routine must return the original filename
( e . g . foo . i - > foo . c ) so can correctly initialize debug output . */
name = ( * lang_hooks . init ) ( name ) ;
if ( name = = NULL )
return 0 ;
/* Is this duplication necessary? */
name = ggc_strdup ( name ) ;
main_input_filename = input_filename = name ;
init_asm_output ( name ) ;
/* These create various _DECL nodes, so need to be called after the
front end is initialized . */
init_eh ( ) ;
init_optabs ( ) ;
/* Put an entry on the input file stack for the main input file. */
push_srcloc ( input_filename , 0 ) ;
/* If dbx symbol table desired, initialize writing it and output the
predefined types . */
timevar_push ( TV_SYMOUT ) ;
# ifdef DWARF2_UNWIND_INFO
if ( dwarf2out_do_frame ( ) )
dwarf2out_frame_init ( ) ;
1999-08-30 04:01:02 +00:00
# endif
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Now we have the correct original filename, we can initialize
debug output . */
( * debug_hooks - > init ) ( name ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
timevar_pop ( TV_SYMOUT ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
return 1 ;
1996-09-18 05:35:50 +00:00
}
2002-02-06 04:59:39 +00:00
/* Clean up: close opened files, etc. */
1996-09-18 05:35:50 +00:00
1999-10-27 09:31:52 +00:00
static void
2002-02-06 04:59:39 +00:00
finalize ( )
1996-09-18 05:35:50 +00:00
{
2002-02-06 04:59:39 +00:00
/* Close the dump files. */
if ( flag_gen_aux_info )
{
fclose ( aux_info_file ) ;
if ( errorcount )
unlink ( aux_info_file_name ) ;
}
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Close non-debugging input and output files. Take special care to note
whether fclose returns an error , since the pages might still be on the
buffer chain while the file is open . */
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
if ( asm_out_file )
{
if ( ferror ( asm_out_file ) ! = 0 )
fatal_io_error ( " error writing to %s " , asm_file_name ) ;
if ( fclose ( asm_out_file ) ! = 0 )
fatal_io_error ( " error closing %s " , asm_file_name ) ;
}
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Do whatever is necessary to finish printing the graphs. */
if ( graph_dump_format ! = no_graph )
{
int i ;
for ( i = 0 ; i < ( int ) DFI_MAX ; + + i )
if ( dump_file [ i ] . initialized & & dump_file [ i ] . graph_dump_p )
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
char seq [ 16 ] ;
char * suffix ;
sprintf ( seq , DUMPFILE_FORMAT , i ) ;
suffix = concat ( seq , dump_file [ i ] . extension , NULL ) ;
finish_graph_dump_file ( dump_base_name , suffix ) ;
free ( suffix ) ;
1999-08-30 04:01:02 +00:00
}
2002-02-06 04:59:39 +00:00
}
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
if ( mem_report )
{
ggc_print_statistics ( ) ;
stringpool_statistics ( ) ;
dump_tree_statistics ( ) ;
}
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Free up memory for the benefit of leak detectors. */
free_reg_info ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Language-specific end of compilation actions. */
( * lang_hooks . finish ) ( ) ;
}
/* Initialize the compiler, and compile the input file. */
static void
do_compile ( )
{
/* The bulk of command line switch processing. */
process_options ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* We cannot start timing until after options are processed since that
says if we run timers or not . */
init_timevar ( ) ;
timevar_start ( TV_TOTAL ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Language-independent initialization. Also sets up GC, identifier
hashes etc . */
lang_independent_init ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
/* Language-dependent initialization. Returns true on success. */
if ( lang_dependent_init ( filename ) )
compile_file ( ) ;
1996-09-18 05:35:50 +00:00
2002-02-06 04:59:39 +00:00
finalize ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Stop timing and print the times. */
timevar_stop ( TV_TOTAL ) ;
timevar_print ( stderr ) ;
1999-08-30 04:01:02 +00:00
}
2002-02-06 04:59:39 +00:00
/* Entry point of cc1, cc1plus, jc1, f771, etc.
Decode command args , then call compile_file .
Exit code is FATAL_EXIT_CODE if can ' t open files or if there were
any errors , or SUCCESS_EXIT_CODE if compilation succeeded .
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
It is not safe to call this function more than once . */
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
int
toplev_main ( argc , argv )
int argc ;
char * * argv ;
1999-08-30 04:01:02 +00:00
{
2002-02-06 04:59:39 +00:00
hex_init ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Initialization of GCC's environment, and diagnostics. */
general_init ( argv [ 0 ] ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Parse the options and do minimal processing; basically just
enough to default flags appropriately . */
parse_options_and_default_flags ( argc , argv ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
/* Exit early if we can (e.g. -help). */
2002-09-01 21:06:42 +00:00
if ( ! errorcount & & ! exit_after_options )
2002-02-06 04:59:39 +00:00
do_compile ( ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
if ( errorcount | | sorrycount )
return ( FATAL_EXIT_CODE ) ;
1999-08-30 04:01:02 +00:00
2002-02-06 04:59:39 +00:00
return ( SUCCESS_EXIT_CODE ) ;
1996-09-18 05:35:50 +00:00
}