1998-03-29 12:14:27 +04:00
/* Top level of GNU C compiler
1998-08-16 21:35:45 +04:00
Copyright ( C ) 1987 , 88 , 89 , 92 - 7 , 1998 Free Software Foundation , Inc .
1998-03-29 12:14:27 +04:00
This file is part of GNU CC .
GNU CC 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 .
GNU CC 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 .
You should have received a copy of the GNU General Public License
along with GNU CC ; see the file COPYING . If not , write to
the Free Software Foundation , 59 Temple Place - Suite 330 ,
Boston , MA 02111 - 1307 , USA . */
/* 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"
# ifdef __STDC__
# include <stdarg.h>
# else
# include <varargs.h>
# endif
1998-08-16 21:35:45 +04:00
# undef FLOAT /* This is for hpux. They should change hpux. */
# undef FFS /* Some systems define this in param.h. */
# include "system.h"
1998-03-29 12:14:27 +04:00
# include <signal.h>
# include <setjmp.h>
# include <sys/stat.h>
1998-08-16 21:35:45 +04:00
# ifdef HAVE_SYS_RESOURCE_H
# include <sys / resource.h>
1998-03-29 12:14:27 +04:00
# endif
1998-08-16 21:35:45 +04:00
# ifdef HAVE_SYS_TIMES_H
# include <sys / times.h>
1998-03-29 12:14:27 +04:00
# endif
# include "input.h"
# include "tree.h"
# include "rtl.h"
# include "flags.h"
# include "insn-attr.h"
1998-08-16 21:35:45 +04:00
# include "insn-codes.h"
# include "insn-config.h"
# include "recog.h"
1998-03-29 12:14:27 +04:00
# include "defaults.h"
# include "output.h"
# include "except.h"
1998-08-16 21:35:45 +04:00
# include "toplev.h"
# ifdef DWARF_DEBUGGING_INFO
# include "dwarfout.h"
# endif
# 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
1998-03-29 12:14:27 +04:00
# ifdef XCOFF_DEBUGGING_INFO
# include "xcoffout.h"
# endif
# ifdef VMS
/* The extra parameters substantially improve the I/O performance. */
static FILE *
vms_fopen ( fname , type )
char * fname ;
char * type ;
{
/* The <stdio.h> in the gcc-vms-1.42 distribution prototypes fopen with two
fixed arguments , which matches ANSI ' s specification but not VAXCRTL ' s
pre - ANSI implementation . This hack circumvents the mismatch problem . */
FILE * ( * vmslib_fopen ) ( ) = ( FILE * ( * ) ( ) ) fopen ;
if ( * type = = ' w ' )
return ( * vmslib_fopen ) ( fname , type , " mbc=32 " ,
" deq=64 " , " fop=tef " , " shr=nil " ) ;
else
return ( * vmslib_fopen ) ( fname , type , " mbc=32 " ) ;
}
# define fopen vms_fopen
# endif /* VMS */
# ifndef DEFAULT_GDB_EXTENSIONS
# define DEFAULT_GDB_EXTENSIONS 1
# endif
/* If more than one debugging type is supported, you must define
PREFERRED_DEBUGGING_TYPE to choose a format in a system - dependent way .
This is one long line cause VAXC can ' t handle a \ - newline . */
# if 1 < (defined (DBX_DEBUGGING_INFO) + defined (SDB_DEBUGGING_INFO) + defined (DWARF_DEBUGGING_INFO) + defined (DWARF2_DEBUGGING_INFO) + defined (XCOFF_DEBUGGING_INFO))
# ifndef PREFERRED_DEBUGGING_TYPE
You Lose ! You must define PREFERRED_DEBUGGING_TYPE !
# endif /* no PREFERRED_DEBUGGING_TYPE */
# else / * Only one debugging format supported. Define PREFERRED_DEBUGGING_TYPE
so the following code needn ' t care . */
# ifdef DBX_DEBUGGING_INFO
# define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
# endif
# ifdef SDB_DEBUGGING_INFO
# define PREFERRED_DEBUGGING_TYPE SDB_DEBUG
# endif
# ifdef DWARF_DEBUGGING_INFO
# define PREFERRED_DEBUGGING_TYPE DWARF_DEBUG
# endif
# ifdef DWARF2_DEBUGGING_INFO
# define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
# endif
# ifdef XCOFF_DEBUGGING_INFO
# define PREFERRED_DEBUGGING_TYPE XCOFF_DEBUG
# endif
# endif /* More than one debugger format enabled. */
/* If still not defined, must have been because no debugging formats
are supported . */
# ifndef PREFERRED_DEBUGGING_TYPE
# define PREFERRED_DEBUGGING_TYPE NO_DEBUG
# endif
extern int rtx_equal_function_value_matters ;
# if ! (defined (VMS) || defined (OS2))
extern char * * environ ;
# endif
extern char * version_string , * language_string ;
/* Carry information from ASM_DECLARE_OBJECT_NAME
to ASM_FINISH_DECLARE_OBJECT . */
extern int size_directive_output ;
extern tree last_assemble_variable_decl ;
1998-08-16 21:35:45 +04:00
extern char * init_parse PVPROTO ( ( char * ) ) ;
extern void finish_parse ( ) ;
1998-03-29 12:14:27 +04:00
extern void init_decl_processing ( ) ;
extern void init_obstacks ( ) ;
extern void init_tree_codes ( ) ;
extern void init_rtl ( ) ;
extern void init_regs ( ) ;
extern void init_optabs ( ) ;
extern void init_stmt ( ) ;
extern void init_reg_sets ( ) ;
extern void dump_flow_info ( ) ;
extern void dump_sched_info ( ) ;
extern void dump_local_alloc ( ) ;
extern void regset_release_memory ( ) ;
1998-08-16 21:35:45 +04:00
extern void print_rtl ( ) ;
extern void print_rtl_with_bb ( ) ;
1998-03-29 12:14:27 +04:00
void rest_of_decl_compilation ( ) ;
void error_with_file_and_line PVPROTO ( ( char * file , int line , char * s , . . . ) ) ;
void error_with_decl PVPROTO ( ( tree decl , char * s , . . . ) ) ;
void error PVPROTO ( ( char * s , . . . ) ) ;
void fatal PVPROTO ( ( char * s , . . . ) ) ;
void warning_with_file_and_line PVPROTO ( ( char * file , int line , char * s , . . . ) ) ;
void warning_with_decl PVPROTO ( ( tree decl , char * s , . . . ) ) ;
void warning PVPROTO ( ( char * s , . . . ) ) ;
void pedwarn PVPROTO ( ( char * s , . . . ) ) ;
void pedwarn_with_decl PVPROTO ( ( tree decl , char * s , . . . ) ) ;
void pedwarn_with_file_and_line PVPROTO ( ( char * file , int line , char * s , . . . ) ) ;
void sorry PVPROTO ( ( char * s , . . . ) ) ;
void really_sorry PVPROTO ( ( char * s , . . . ) ) ;
void fancy_abort ( ) ;
void set_target_switch ( ) ;
1998-08-16 21:35:45 +04:00
static char * decl_name PROTO ( ( tree , int ) ) ;
static void vmessage PROTO ( ( char * , char * , va_list ) ) ;
static void v_message_with_file_and_line PROTO ( ( char * , int , char * ,
char * , va_list ) ) ;
static void v_message_with_decl PROTO ( ( tree , char * , char * , va_list ) ) ;
static void file_and_line_for_asm PROTO ( ( rtx , char * * , int * ) ) ;
static void v_error_with_file_and_line PROTO ( ( char * , int , char * , va_list ) ) ;
static void v_error_with_decl PROTO ( ( tree , char * , va_list ) ) ;
static void v_error_for_asm PROTO ( ( rtx , char * , va_list ) ) ;
static void verror PROTO ( ( char * , va_list ) ) ;
static void vfatal PROTO ( ( char * , va_list ) ) ;
static void v_warning_with_file_and_line PROTO ( ( char * , int , char * , va_list ) ) ;
static void v_warning_with_decl PROTO ( ( tree , char * , va_list ) ) ;
static void v_warning_for_asm PROTO ( ( rtx , char * , va_list ) ) ;
static void vwarning PROTO ( ( char * , va_list ) ) ;
static void vpedwarn PROTO ( ( char * , va_list ) ) ;
static void v_pedwarn_with_decl PROTO ( ( tree , char * , va_list ) ) ;
static void v_pedwarn_with_file_and_line PROTO ( ( char * , int , char * , va_list ) ) ;
static void vsorry PROTO ( ( char * , va_list ) ) ;
static void v_really_sorry PROTO ( ( char * , va_list ) ) ;
static void float_signal PROTO ( ( int ) ) ;
static void pipe_closed PROTO ( ( int ) ) ;
static void output_lang_identify PROTO ( ( FILE * ) ) ;
static void open_dump_file PROTO ( ( char * , char * ) ) ;
static void close_dump_file PROTO ( ( void ( * ) ( FILE * , rtx ) , rtx ) ) ;
static void dump_rtl PROTO ( ( char * , tree , void ( * ) ( FILE * , rtx ) , rtx ) ) ;
static void clean_dump_file PROTO ( ( char * ) ) ;
static void compile_file PROTO ( ( char * ) ) ;
static void display_help PROTO ( ( void ) ) ;
1998-03-29 12:14:27 +04:00
void print_version ( ) ;
int print_single_switch ( ) ;
void print_switch_values ( ) ;
/* Length of line when printing switch values. */
# define MAX_LINE 75
/* Name of program invoked, sans directories. */
char * progname ;
/* Copy of arguments to main. */
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 . */
char * input_filename ;
/* 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 . */
char * main_input_filename ;
/* Current line number in real source file. */
int lineno ;
/* 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 ;
/* FUNCTION_DECL for function now being parsed or compiled. */
extern tree current_function_decl ;
/* Name to use as base of names for dump output files. */
char * dump_base_name ;
/* 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 ;
/* Flags saying which kinds of debugging dump have been requested. */
int rtl_dump = 0 ;
int rtl_dump_and_exit = 0 ;
int jump_opt_dump = 0 ;
1998-08-16 21:35:45 +04:00
int addressof_dump = 0 ;
1998-03-29 12:14:27 +04:00
int cse_dump = 0 ;
1998-08-16 21:35:45 +04:00
int gcse_dump = 0 ;
1998-03-29 12:14:27 +04:00
int loop_dump = 0 ;
int cse2_dump = 0 ;
int branch_prob_dump = 0 ;
int flow_dump = 0 ;
int combine_dump = 0 ;
int regmove_dump = 0 ;
int sched_dump = 0 ;
int local_reg_dump = 0 ;
int global_reg_dump = 0 ;
int sched2_dump = 0 ;
int jump2_opt_dump = 0 ;
1998-08-16 21:35:45 +04:00
# ifdef DELAY_SLOTS
1998-03-29 12:14:27 +04:00
int dbr_sched_dump = 0 ;
1998-08-16 21:35:45 +04:00
# endif
1998-03-29 12:14:27 +04:00
int flag_print_asm_name = 0 ;
1998-08-16 21:35:45 +04:00
# ifdef STACK_REGS
1998-03-29 12:14:27 +04:00
int stack_reg_dump = 0 ;
1998-08-16 21:35:45 +04:00
# endif
# ifdef MACHINE_DEPENDENT_REORG
int mach_dep_reorg_dump = 0 ;
# endif
1998-03-29 12:14:27 +04: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 ;
1998-08-16 21:35:45 +04: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 ;
1998-03-29 12:14:27 +04:00
/* Number of error messages and warning messages so far. */
int errorcount = 0 ;
int warningcount = 0 ;
int sorrycount = 0 ;
/* 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 + + . */
char * ( * decl_printable_name ) ( /* tree decl, int verbosity */ ) ;
/* Pointer to function to compute rtl for a language-specific tree code. */
struct rtx_def * ( * lang_expand_expr ) ( ) ;
/* Pointer to function to finish handling an incomplete decl at the
end of compilation . */
void ( * incomplete_decl_finalize_hook ) ( ) = 0 ;
/* Highest label number used at the end of reload. */
int max_label_num_after_reload ;
/* Nonzero if generating code to do profiling. */
int profile_flag = 0 ;
/* Nonzero if generating code to do profiling on a line-by-line basis. */
int profile_block_flag ;
/* 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 ;
/* 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 ;
/* Nonzero means do stupid register allocation.
Currently , this is 1 if ` optimize ' is 0. */
int obey_regdecls = 0 ;
/* Don't print functions as they are compiled and don't print
times taken by the various passes . - quiet . */
int quiet_flag = 0 ;
/* -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 ;
/* Nonzero forces all invariant computations in loops to be moved
outside the loop . */
int flag_move_all_movables = 0 ;
/* Nonzero forces all general induction variables in loops to be
strength reduced . */
int flag_reduce_all_givs = 0 ;
1998-08-16 21:35:45 +04:00
/* Nonzero to perform full register move optimization passes. This is the
default for - O2 . */
int flag_regmove = 0 ;
1998-03-29 12:14:27 +04: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 ;
/* 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 ;
/* Nonzero to inhibit use of define_optimization peephole opts. */
int flag_no_peephole = 0 ;
/* Nonzero allows GCC to violate some IEEE or ANSI rules regarding math
operations in the interest of optimization . For example it allows
GCC to assume arguments to sqrt are nonnegative numbers , allowing
faster code for sqrt to be generated . */
int flag_fast_math = 0 ;
/* Nonzero means all references through pointers are volatile. */
int flag_volatile ;
/* Nonzero means treat all global and extern variables as global. */
int flag_volatile_global ;
/* Nonzero means just do syntax checking; don't output anything. */
int flag_syntax_only = 0 ;
1998-08-16 21:35:45 +04:00
/* Nonzero means perform global cse. */
static int flag_gcse ;
1998-03-29 12:14:27 +04: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-04-06 19:07:33 +04:00
/* Nonzero means to assume that a structure or an array reference at
a varying address cannot alias a scalar at a fixed address . */
int flag_structure_noalias = 0 ;
1998-03-29 12:14:27 +04:00
/* Nonzero means to run loop optimizations twice. */
int flag_rerun_loop_opt ;
/* 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. */
int flag_no_inline ;
/* Nonzero means that we should emit static const variables
regardless of whether or not optimization is turned on . */
int flag_keep_static_consts = 1 ;
/* 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 ;
/* Nonzero means generate extra code for exception handling and enable
exception handling . */
1998-08-16 21:35:45 +04:00
int flag_exceptions ;
/* Nonzero means use the new model for exception handling. Replaces
- DNEW_EH_MODEL as a compile option . */
int flag_new_exceptions = 0 ;
1998-03-29 12:14:27 +04:00
/* Nonzero means don't place uninitialized global data in common storage
by default . */
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 ;
# ifdef HAIFA
/* 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
1998-08-16 21:35:45 +04:00
load insns . */
1998-03-29 12:14:27 +04:00
int flag_schedule_interblock = 1 ;
int flag_schedule_speculative = 1 ;
int flag_schedule_speculative_load = 0 ;
int flag_schedule_speculative_load_dangerous = 0 ;
/* flag_on_branch_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 ;
# endif /* HAIFA */
/* -finhibit-size-directive inhibits output of .size for ELF.
This is used only for compiling crtstuff . c ,
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
generated assembly code ( perhaps while debugging the compiler itself ) .
1998-08-16 21:35:45 +04:00
- fno - verbose - asm , the default , causes the extra information
1998-03-29 12:14:27 +04:00
to be omitted and is useful when comparing two assembler files . */
1998-08-16 21:35:45 +04:00
int flag_verbose_asm = 0 ;
1998-03-29 12:14:27 +04: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 ;
/* -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
/* Tag all structures with __attribute__(packed) */
int flag_pack_struct = 0 ;
/* Emit code to check for stack overflow; also may cause large objects
to be allocated dynamically . */
int flag_stack_check ;
/* -fcheck-memory-usage causes extra code to be generated in order to check
memory accesses . This is used by a detector of bad memory accesses such
as Checker . */
int flag_check_memory_usage = 0 ;
/* -fprefix-function-name causes function name to be prefixed. This
can be used with - fcheck - memory - usage to isolate code compiled with
- fcheck - memory - usage . */
int flag_prefix_function_name = 0 ;
/* 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 ;
1998-08-16 21:35:45 +04:00
/* 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 ;
extern int flag_dump_unnumbered ;
/* Table of supported debugging formats. */
static struct
{
char * arg ;
/* Since PREFERRED_DEBUGGING_TYPE isn't necessarily a
constant expression , we use NO_DEBUG in its place . */
enum debug_info_type debug_type ;
int use_extensions_p ;
char * description ;
} * da ,
debug_args [ ] =
{
{ " g " , NO_DEBUG , DEFAULT_GDB_EXTENSIONS ,
" Generate default debug format output " } ,
{ " ggdb " , NO_DEBUG , 1 , " Generate default extended debug format output " } ,
# ifdef DBX_DEBUGGING_INFO
{ " gstabs " , DBX_DEBUG , 0 , " Generate STABS format debug output " } ,
{ " gstabs+ " , DBX_DEBUG , 1 , " Generate extended STABS format debug output " } ,
# endif
# ifdef DWARF_DEBUGGING_INFO
{ " gdwarf " , DWARF_DEBUG , 0 , " Generate DWARF-1 format debug output " } ,
{ " gdwarf+ " , DWARF_DEBUG , 1 ,
" Generated extended DWARF-1 format debug output " } ,
# endif
# ifdef DWARF2_DEBUGGING_INFO
{ " gdwarf-2 " , DWARF2_DEBUG , 0 , " Enable DWARF-2 debug output " } ,
# endif
# ifdef XCOFF_DEBUGGING_INFO
{ " gxcoff " , XCOFF_DEBUG , 0 , " Generate XCOFF format debug output " } ,
{ " gxcoff+ " , XCOFF_DEBUG , 1 , " Generate extended XCOFF format debug output " } ,
# endif
# ifdef SDB_DEBUGGING_INFO
{ " gcoff " , SDB_DEBUG , 0 , " Generate COFF format debug output " } ,
# endif
{ 0 , 0 , 0 }
} ;
typedef struct
{
char * string ;
int * variable ;
int on_value ;
char * description ;
}
lang_independent_options ;
1998-03-29 12:14:27 +04: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 . ) */
1998-08-16 21:35:45 +04:00
lang_independent_options f_options [ ] =
1998-03-29 12:14:27 +04:00
{
1998-08-16 21:35:45 +04:00
{ " float-store " , & flag_float_store , 1 ,
" Do not store floats in registers " } ,
{ " volatile " , & flag_volatile , 1 ,
" Consider all mem refs through pointers as volatile " } ,
{ " volatile-global " , & flag_volatile_global , 1 ,
" Consider all mem refs to global data to be volatile " } ,
{ " defer-pop " , & flag_defer_pop , 1 ,
" Defer popping functions args from stack until later " } ,
{ " omit-frame-pointer " , & flag_omit_frame_pointer , 1 ,
" When possible do not generate stack frames " } ,
{ " cse-follow-jumps " , & flag_cse_follow_jumps , 1 ,
" When running CSE, follow jumps to their targets " } ,
{ " cse-skip-blocks " , & flag_cse_skip_blocks , 1 ,
" When running CSE, follow conditional jumps " } ,
{ " expensive-optimizations " , & flag_expensive_optimizations , 1 ,
" Perform a number of minor, expensive optimisations " } ,
{ " thread-jumps " , & flag_thread_jumps , 1 ,
" Perform jump threading optimisations " } ,
{ " strength-reduce " , & flag_strength_reduce , 1 ,
" Perform strength reduction optimisations " } ,
{ " unroll-loops " , & flag_unroll_loops , 1 ,
" Perform loop unrolling when interation count is known " } ,
{ " unroll-all-loops " , & flag_unroll_all_loops , 1 ,
" Perofm loop onrolling for all loops " } ,
{ " move-all-movables " , & flag_move_all_movables , 1 ,
" Force all loop invariant computations out of loops " } ,
{ " reduce-all-givs " , & flag_reduce_all_givs , 1 ,
" Strength reduce all loop general induction variables " } ,
{ " writable-strings " , & flag_writable_strings , 1 ,
" Store strings in writable data section " } ,
{ " peephole " , & flag_no_peephole , 0 ,
" Enable machine specific peephole optimisations " } ,
{ " force-mem " , & flag_force_mem , 1 ,
" Copy memory operands into registers before using " } ,
{ " force-addr " , & flag_force_addr , 1 ,
" Copy memory address constants into regs before using " } ,
{ " function-cse " , & flag_no_function_cse , 0 ,
" Allow function addresses to be held in registers " } ,
{ " inline-functions " , & flag_inline_functions , 1 ,
" Integrate simple functions into their callers " } ,
{ " keep-inline-functions " , & flag_keep_inline_functions , 1 ,
" Generate code for funcs even if they are fully inlined " } ,
{ " inline " , & flag_no_inline , 0 ,
" Pay attention to the 'inline' keyword " } ,
{ " keep-static-consts " , & flag_keep_static_consts , 1 ,
" Emit static const variables even if they are not used " } ,
{ " syntax-only " , & flag_syntax_only , 1 ,
" Check for syntax errors, then stop " } ,
{ " shared-data " , & flag_shared_data , 1 ,
" Mark data as shared rather than private " } ,
{ " caller-saves " , & flag_caller_saves , 1 ,
" Enable saving registers around function calls " } ,
{ " pcc-struct-return " , & flag_pcc_struct_return , 1 ,
" Return 'short' aggregates in memory, not registers " } ,
{ " reg-struct-return " , & flag_pcc_struct_return , 0 ,
" Return 'short' aggregates in registers " } ,
{ " delayed-branch " , & flag_delayed_branch , 1 ,
" Attempt to fill delay slots of branch instructions " } ,
{ " gcse " , & flag_gcse , 1 ,
" Perform the global common subexpression elimination " } ,
{ " rerun-cse-after-loop " , & flag_rerun_cse_after_loop , 1 ,
" Run CSE pass after loop optimisations " } ,
1999-04-06 19:07:33 +04:00
{ " structure-noalias " , & flag_structure_noalias , 1 ,
" Assume structure / array reference and fixed scalar cannot alias " } ,
1998-08-16 21:35:45 +04:00
{ " rerun-loop-opt " , & flag_rerun_loop_opt , 1 ,
" Run the loop optimiser twice " } ,
{ " pretend-float " , & flag_pretend_float , 1 ,
" Pretend that host and target use the same FP format " } ,
{ " schedule-insns " , & flag_schedule_insns , 1 ,
" Reschedule instructions to avoid pipeline stalls " } ,
{ " schedule-insns2 " , & flag_schedule_insns_after_reload , 1 ,
" Run two passes of the instruction scheduler " } ,
1998-03-29 12:14:27 +04:00
# ifdef HAIFA
1998-08-16 21:35:45 +04:00
{ " sched-interblock " , & flag_schedule_interblock , 1 ,
" Enable scheduling across basic blocks " } ,
{ " sched-spec " , & flag_schedule_speculative , 1 ,
" Allow speculative motion of non-loads " } ,
{ " sched-spec-load " , & flag_schedule_speculative_load , 1 ,
" Allow speculative motion of some loads " } ,
{ " sched-spec-load-dangerous " , & flag_schedule_speculative_load_dangerous , 1 ,
" Allow speculative motion of more loads " } ,
{ " branch-count-reg " , & flag_branch_on_count_reg , 1 ,
" Replace add,compare,branch with branch on count reg " } ,
1998-03-29 12:14:27 +04:00
# endif /* HAIFA */
1998-08-16 21:35:45 +04:00
{ " pic " , & flag_pic , 1 ,
" Generate position independent code, if possible " } ,
{ " PIC " , & flag_pic , 2 , " " } ,
{ " exceptions " , & flag_exceptions , 1 ,
" Enable exception handling " } ,
{ " new-exceptions " , & flag_new_exceptions , 1 ,
" Use the new model for exception handling " } ,
{ " sjlj-exceptions " , & exceptions_via_longjmp , 1 ,
" Use setjmp/longjmp to handle exceptions " } ,
{ " asynchronous-exceptions " , & asynchronous_exceptions , 1 ,
" Support asynchronous exceptions " } ,
{ " profile-arcs " , & profile_arc_flag , 1 ,
" Insert arc based program profiling code " } ,
{ " test-coverage " , & flag_test_coverage , 1 ,
" Create data files needed by gcov " } ,
{ " branch-probabilities " , & flag_branch_probabilities , 1 ,
" Use profiling information for branch porbabilities " } ,
{ " fast-math " , & flag_fast_math , 1 ,
" Improve FP speed by violating ANSI & IEEE rules " } ,
{ " common " , & flag_no_common , 0 ,
" Do not put unitialised globals in the common section " } ,
{ " inhibit-size-directive " , & flag_inhibit_size_directive , 1 ,
" Do not generate .size directives " } ,
{ " function-sections " , & flag_function_sections , 1 ,
" place each function into its own section " } ,
{ " verbose-asm " , & flag_verbose_asm , 1 ,
" Add extra commentry to assembler output " } ,
{ " gnu-linker " , & flag_gnu_linker , 1 ,
" Output GNU ld formatted global initialisers " } ,
{ " regmove " , & flag_regmove , 1 ,
" Enables a regoster move optimisation " } ,
{ " optimize-register-move " , & flag_regmove , 1 } ,
{ " pack-struct " , & flag_pack_struct , 1 ,
" Pack structure members together without holes " } ,
{ " stack-check " , & flag_stack_check , 1 ,
" Insert stack checking code into the program " } ,
{ " argument-alias " , & flag_argument_noalias , 0 ,
" Specify that arguments may alias each other & globals " } ,
{ " argument-noalias " , & flag_argument_noalias , 1 ,
" Assume arguments may alias globals but not each other " } ,
{ " argument-noalias-global " , & flag_argument_noalias , 2 ,
" Assume arguments do not alias each other or globals " } ,
{ " strict-aliasing " , & flag_strict_aliasing , 1 ,
" Assume strict aliasing rules apply " } ,
{ " check-memory-usage " , & flag_check_memory_usage , 1 ,
" Generate code to check every memory access " } ,
{ " prefix-function-name " , & flag_prefix_function_name , 1 ,
" Add a prefix to all function names " } ,
{ " dump-unnumbered " , & flag_dump_unnumbered , 1 }
1998-03-29 12:14:27 +04:00
} ;
1998-08-16 21:35:45 +04:00
# define NUM_ELEM(a) (sizeof (a) / sizeof ((a)[0]))
1998-03-29 12:14:27 +04:00
/* Table of language-specific options. */
1998-08-16 21:35:45 +04:00
static struct lang_opt
{
char * option ;
char * description ;
}
documented_lang_options [ ] =
1998-03-29 12:14:27 +04:00
{
1998-08-16 21:35:45 +04:00
/* In order not to overload the --help output, the convention
used here is to only describe those options which are not
enabled by default . */
{ " -ansi " , " Compile just for ANSI C " } ,
{ " -fallow-single-precision " ,
" Do not promote floats to double if using -traditional " } ,
{ " -fsigned-bitfields " , " " } ,
{ " -funsigned-bitfields " , " Make bitfields by unsigned by default " } ,
{ " -fno-signed-bitfields " , " " } ,
{ " -fno-unsigned-bitfields " , " " } ,
{ " -fsigned-char " , " Make 'char' be signed by default " } ,
{ " -funsigned-char " , " Make 'char' be unsigned by default " } ,
{ " -fno-signed-char " , " " } ,
{ " -fno-unsigned-char " , " " } ,
{ " -ftraditional " , " " } ,
{ " -traditional " , " Attempt to support traditional K&R style C " } ,
{ " -fnotraditional " , " " } ,
{ " -fno-traditional " , " " } ,
{ " -fasm " , " " } ,
{ " -fno-asm " , " Do not recognise the 'asm' keyword " } ,
{ " -fbuiltin " , " " } ,
{ " -fno-builtin " , " Do not recognise any built in functions " } ,
{ " -fhosted " , " Assume normal C execution environment " } ,
{ " -fno-hosted " , " " } ,
{ " -ffreestanding " ,
" Assume that standard libraries & main might not exist " } ,
{ " -fno-freestanding " , " " } ,
{ " -fcond-mismatch " , " Allow different types as args of ? operator " } ,
{ " -fno-cond-mismatch " , " " } ,
{ " -fdollars-in-identifiers " , " Allow the use of $ inside indentifiers " } ,
{ " -fno-dollars-in-identifiers " , " " } ,
{ " -fident " , " " } ,
{ " -fno-ident " , " Ignore #ident directives " } ,
{ " -fshort-double " , " Use the same size for double as for float " } ,
{ " -fno-short-double " , " " } ,
{ " -fshort-enums " , " Use the smallest fitting integer to hold enums " } ,
{ " -fno-short-enums " , " " } ,
{ " -Wall " , " Enable most warning messages " } ,
{ " -Wbad-function-cast " ,
" Warn about casting functions to incompatible types " } ,
{ " -Wno-bad-function-cast " , " " } ,
{ " -Wcast-qual " , " Warn about casts which discard qualifiers " } ,
{ " -Wno-cast-qual " , " " } ,
{ " -Wchar-subscripts " , " Warn about subscripts whoes type is 'char' " } ,
{ " -Wno-char-subscripts " , " " } ,
{ " -Wcomment " , " Warn if nested comments are detected " } ,
{ " -Wno-comment " , } ,
{ " -Wcomments " , } ,
{ " -Wno-comments " , } ,
{ " -Wconversion " , " Warn about possibly confusing type conversions " } ,
{ " -Wno-conversion " , " " } ,
{ " -Wformat " , " Warn about printf format anomalies " } ,
Enhanced format string checking.
If -Wformat is enabled, try harder to chase down compile-time constant
format strings.. capable of catching things like:
const char foo[]="%s %d";
printf(foo, 1, "2");
If the new option -Wnetbsd-format-audit (no, I don't like the name,
either) is enabled, complain about non-constant format strings we
can't verify. In particular, for *v*printf-like functions (i.e.,
non-variadic functions which are passed a va_list), insist that the
format string come from a parameter declared as a format string
argument, so that functions which should be declared as printflike are
caught at compile time.
2000-10-04 23:21:28 +04:00
{ " -Wnetbsd-format-audit " , " NetBSD format audit " } ,
1998-08-16 21:35:45 +04:00
{ " -Wno-format " , " " } ,
2000-10-05 17:08:57 +04:00
{ " -Wno-format-extra-args " , " " } ,
1998-08-16 21:35:45 +04:00
{ " -Wimplicit-function-declaration " ,
" Warn about implicit function declarations " } ,
{ " -Wno-implicit-function-declaration " , " " } ,
{ " -Werror-implicit-function-declaration " , " " } ,
{ " -Wimplicit-int " , " Warn when a declaration does not specify a type " } ,
{ " -Wno-implicit-int " , " " } ,
{ " -Wimplicit " , " " } ,
{ " -Wno-implicit " , " " } ,
{ " -Wimport " , " Warn about the use of the #import directive " } ,
{ " -Wno-import " , " " } ,
{ " -Wlong-long " , " " } ,
{ " -Wno-long-long " , " Do not warn about using 'long long' when -pedantic " } ,
{ " -Wmain " , " Warn about suspicious declarations of main " } ,
{ " -Wno-main " , " " } ,
{ " -Wmissing-braces " ,
" Warn about possibly missing braces around initialisers " } ,
{ " -Wno-missing-braces " , " " } ,
{ " -Wmissing-declarations " ,
" Warn about global funcs without previous declarations " } ,
{ " -Wno-missing-declarations " , " " } ,
{ " -Wmissing-prototypes " , " Warn about global funcs without prototypes " } ,
{ " -Wno-missing-prototypes " , " " } ,
{ " -Wmultichar " , " Warn about use of multicharacter literals " } ,
{ " -Wno-multichar " , " " } ,
{ " -Wnested-externs " , " Warn about externs not at file scope level " } ,
{ " -Wno-nested-externs " , " " } ,
{ " -Wparentheses " , " Warn about possible missing parentheses " } ,
{ " -Wno-parentheses " , " " } ,
{ " -Wpointer-arith " , " Warn about function pointer arithmetic " } ,
{ " -Wno-pointer-arith " , " " } ,
{ " -Wredundant-decls " ,
" Warn about multiple declarations of the same object " } ,
{ " -Wno-redundant-decls " , " " } ,
{ " -Wsign-compare " , " Warn about signed/unsigned comparisons " } ,
{ " -Wno-sign-compare " , " " } ,
{ " -Wunknown-pragmas " , " Warn about unrecognised pragmas " } ,
{ " -Wno-unknown-pragmas " , " " } ,
{ " -Wstrict-prototypes " , " Warn about non-prototyped function decls " } ,
{ " -Wno-strict-prototypes " , " " } ,
{ " -Wtraditional " , " Warn about constructs whoes meaning change in ANSI C " } ,
{ " -Wno-traditional " , " " } ,
{ " -Wtrigraphs " , " Warn when trigraphs are encountered " } ,
{ " -Wno-trigraphs " , " " } ,
{ " -Wundef " , " " } ,
{ " -Wno-undef " , " " } ,
{ " -Wwrite-strings " , " Mark strings as 'const char *' " } ,
{ " -Wno-write-strings " , " " } ,
/* These are for languages with USE_CPPLIB. */
/* These options are already documented in cpplib.c */
{ " --help " , " " } ,
{ " -A " , " " } ,
{ " -D " , " " } ,
{ " -I " , " " } ,
{ " -U " , " " } ,
{ " -idirafter " , " " } ,
{ " -iprefix " , " " } ,
{ " -isystem " , " " } ,
{ " -lang-c " , " " } ,
{ " -lang-c89 " , " " } ,
{ " -lang-c++ " , " " } ,
{ " -nostdinc " , " " } ,
{ " -nostdinc++ " , " " } ,
{ " -trigraphs " , " " } ,
{ " -undef " , " " } ,
{ " -remap " , " " } ,
# define DEFINE_LANG_NAME(NAME) { NULL, NAME },
/* These are for obj c. */
DEFINE_LANG_NAME ( " Objective C " )
{ " -lang-objc " , " " } ,
{ " -gen-decls " , " Dump decls to a .decl file " } ,
{ " -fgnu-runtime " , " Generate code for GNU runtime envrionment " } ,
{ " -fno-gnu-runtime " , " " } ,
{ " -fnext-runtime " , " Generate code for NeXT runtime environment " } ,
{ " -fno-next-runtime " , " " } ,
{ " -Wselector " , " Warn if a selector has multiple methods " } ,
{ " -Wno-selector " , " " } ,
{ " -Wprotocol " , " " } ,
{ " -Wno-protocol " , " Do not warn if inherited methods are unimplemented " } ,
{ " -print-objc-runtime-info " ,
" Generate C header of platform specific features " } ,
1998-03-29 12:14:27 +04:00
# include "options.h"
1998-08-16 21:35:45 +04:00
1998-03-29 12:14:27 +04:00
} ;
1998-08-16 21:35:45 +04: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 . ) */
struct
{
char * name ;
int value ;
char * description ;
}
target_switches [ ] = TARGET_SWITCHES ;
/* This table is similar, but allows the switch to have a value. */
# ifdef TARGET_OPTIONS
struct
{
char * prefix ;
char * * variable ;
char * description ;
}
target_options [ ] = TARGET_OPTIONS ;
# endif
1998-03-29 12:14:27 +04:00
/* Options controlling warnings */
/* Don't print warning messages. -w. */
int inhibit_warnings = 0 ;
/* Print various extra warnings. -W. */
int extra_warnings = 0 ;
/* Treat warnings as errors. -Werror. */
int warnings_are_errors = 0 ;
/* Nonzero to warn about unused local variables. */
int warn_unused ;
/* Nonzero to warn about variables used before they are initialized. */
int warn_uninitialized ;
/* Nonzero means warn about all declarations which shadow others. */
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 identifiers that match in the first N
characters . The value N is in ` id_clash_len ' . */
int warn_id_clash ;
unsigned id_clash_len ;
/* 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 ' . */
int warn_larger_than ;
unsigned larger_than_size ;
/* 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 ;
/* Likewise for -W. */
1998-08-16 21:35:45 +04:00
lang_independent_options W_options [ ] =
1998-03-29 12:14:27 +04:00
{
1998-08-16 21:35:45 +04:00
{ " unused " , & warn_unused , 1 , " Warn when a variable is unused " } ,
{ " error " , & warnings_are_errors , 1 , " " } ,
{ " shadow " , & warn_shadow , 1 , " Warn when one local variable shadows another " } ,
{ " switch " , & warn_switch , 1 ,
" Warn about enumerated switches missing a specific case " } ,
{ " aggregate-return " , & warn_aggregate_return , 1 ,
" Warn about returning structures, unions or arrays " } ,
{ " cast-align " , & warn_cast_align , 1 ,
" Warn about pointer casts which increase alignment " } ,
{ " uninitialized " , & warn_uninitialized , 1 ,
" Warn about unitialized automatic variables " } ,
{ " inline " , & warn_inline , 1 ,
" Warn when an inlined function cannot be inlined " }
1998-03-29 12:14:27 +04:00
} ;
/* Output files for assembler code (real compiler output)
and debugging dumps . */
FILE * asm_out_file ;
FILE * aux_info_file ;
1998-08-16 21:35:45 +04:00
FILE * rtl_dump_file = NULL ;
1998-03-29 12:14:27 +04:00
/* Time accumulators, to count the total time spent in various passes. */
int parse_time ;
int varconst_time ;
int integration_time ;
int jump_time ;
int cse_time ;
1998-08-16 21:35:45 +04:00
int gcse_time ;
1998-03-29 12:14:27 +04:00
int loop_time ;
int cse2_time ;
int branch_prob_time ;
int flow_time ;
int combine_time ;
int regmove_time ;
int sched_time ;
int local_alloc_time ;
int global_alloc_time ;
int sched2_time ;
1998-08-16 21:35:45 +04:00
# ifdef DELAY_SLOTS
1998-03-29 12:14:27 +04:00
int dbr_sched_time ;
1998-08-16 21:35:45 +04:00
# endif
1998-03-29 12:14:27 +04:00
int shorten_branch_time ;
int stack_reg_time ;
int final_time ;
int symout_time ;
int dump_time ;
/* Return time used so far, in microseconds. */
int
get_run_time ( )
{
if ( quiet_flag )
return 0 ;
1998-08-16 21:35:45 +04:00
# ifdef __BEOS__
return 0 ;
# else /* not BeOS */
# if defined (_WIN32) && !defined (__CYGWIN32__)
1998-03-29 12:14:27 +04:00
if ( clock ( ) < 0 )
return 0 ;
else
return ( clock ( ) * 1000 ) ;
# else /* not _WIN32 */
1998-08-16 21:35:45 +04:00
# ifdef _SC_CLK_TCK
{
static int tick ;
struct tms tms ;
if ( tick = = 0 )
tick = 1000000 / sysconf ( _SC_CLK_TCK ) ;
times ( & tms ) ;
return ( tms . tms_utime + tms . tms_stime ) * tick ;
}
# else
1998-03-29 12:14:27 +04:00
# ifdef USG
1998-08-16 21:35:45 +04:00
{
struct tms tms ;
# if HAVE_SYSCONF && defined _SC_CLK_TCK
# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
# else
# ifdef CLK_TCK
# define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
# else
# define TICKS_PER_SECOND HZ /* traditional UNIX */
# endif
# endif
times ( & tms ) ;
return ( tms . tms_utime + tms . tms_stime ) * ( 1000000 / TICKS_PER_SECOND ) ;
}
1998-03-29 12:14:27 +04:00
# else
# ifndef VMS
1998-08-16 21:35:45 +04:00
{
struct rusage rusage ;
getrusage ( 0 , & rusage ) ;
return ( rusage . ru_utime . tv_sec * 1000000 + rusage . ru_utime . tv_usec
+ rusage . ru_stime . tv_sec * 1000000 + rusage . ru_stime . tv_usec ) ;
}
1998-03-29 12:14:27 +04:00
# else /* VMS */
1998-08-16 21:35:45 +04:00
{
struct
{
int proc_user_time ;
int proc_system_time ;
int child_user_time ;
int child_system_time ;
} vms_times ;
times ( ( void * ) & vms_times ) ;
return ( vms_times . proc_user_time + vms_times . proc_system_time ) * 10000 ;
}
# endif /* VMS */
# endif /* USG */
# endif /* _SC_CLK_TCK */
# endif /* _WIN32 */
# endif /* __BEOS__ */
1998-03-29 12:14:27 +04:00
}
# define TIMEVAR(VAR, BODY) \
do { int otime = get_run_time ( ) ; BODY ; VAR + = get_run_time ( ) - otime ; } while ( 0 )
void
print_time ( str , total )
char * str ;
int total ;
{
fprintf ( stderr ,
" time in %s: %d.%06d \n " ,
str , total / 1000000 , total % 1000000 ) ;
}
/* Count an error or warning. Return 1 if the message should be printed. */
int
count_error ( warningp )
int warningp ;
{
if ( warningp & & inhibit_warnings )
return 0 ;
if ( warningp & & ! warnings_are_errors )
warningcount + + ;
else
{
static int warning_message = 0 ;
if ( warningp & & ! warning_message )
{
fprintf ( stderr , " %s: warnings being treated as errors \n " , progname ) ;
warning_message = 1 ;
}
errorcount + + ;
}
return 1 ;
}
/* Print a fatal error message. NAME is the text.
Also include a system error message based on ` errno ' . */
void
pfatal_with_name ( name )
char * name ;
{
fprintf ( stderr , " %s: " , progname ) ;
perror ( name ) ;
exit ( FATAL_EXIT_CODE ) ;
}
void
fatal_io_error ( name )
char * name ;
{
fprintf ( stderr , " %s: %s: I/O error \n " , progname , name ) ;
exit ( FATAL_EXIT_CODE ) ;
}
/* Called to give a better error message for a bad insn rather than
just calling abort ( ) . */
void
fatal_insn ( message , insn )
char * message ;
rtx insn ;
{
1998-08-16 21:35:45 +04:00
error ( message ) ;
debug_rtx ( insn ) ;
1998-03-29 12:14:27 +04:00
if ( asm_out_file )
fflush ( asm_out_file ) ;
if ( aux_info_file )
fflush ( aux_info_file ) ;
1998-08-16 21:35:45 +04:00
if ( rtl_dump_file ! = NULL )
1998-03-29 12:14:27 +04:00
fflush ( rtl_dump_file ) ;
fflush ( stdout ) ;
fflush ( stderr ) ;
abort ( ) ;
}
/* Called to give a better error message when we don't have an insn to match
what we are looking for or if the insn ' s constraints aren ' t satisfied ,
rather than just calling abort ( ) . */
void
fatal_insn_not_found ( insn )
rtx insn ;
{
if ( INSN_CODE ( insn ) < 0 )
fatal_insn ( " internal error--unrecognizable insn: " , insn ) ;
else
fatal_insn ( " internal error--insn does not satisfy its constraints: " , insn ) ;
}
/* This is the default decl_printable_name function. */
static char *
decl_name ( decl , verbosity )
tree decl ;
int verbosity ;
{
return IDENTIFIER_POINTER ( DECL_NAME ( decl ) ) ;
}
static int need_error_newline ;
/* Function of last error message;
more generally , function such that if next error message is in it
then we don ' t have to mention the function name . */
static tree last_error_function = NULL ;
/* Used to detect when input_file_stack has changed since last described. */
static int last_error_tick ;
/* Called when the start of a function definition is parsed,
this function prints on stderr the name of the function . */
void
announce_function ( decl )
tree decl ;
{
if ( ! quiet_flag )
{
if ( rtl_dump_and_exit )
fprintf ( stderr , " %s " , IDENTIFIER_POINTER ( DECL_NAME ( decl ) ) ) ;
else
fprintf ( stderr , " %s " , ( * decl_printable_name ) ( decl , 2 ) ) ;
fflush ( stderr ) ;
need_error_newline = 1 ;
last_error_function = current_function_decl ;
}
}
/* The default function to print out name of current function that caused
an error . */
void
default_print_error_function ( file )
char * file ;
{
if ( last_error_function ! = current_function_decl )
{
char * kind = " function " ;
if ( current_function_decl ! = 0
& & TREE_CODE ( TREE_TYPE ( current_function_decl ) ) = = METHOD_TYPE )
kind = " method " ;
if ( file )
fprintf ( stderr , " %s: " , file ) ;
if ( current_function_decl = = NULL )
fprintf ( stderr , " At top level: \n " ) ;
else
{
char * name = ( * decl_printable_name ) ( current_function_decl , 2 ) ;
fprintf ( stderr , " In %s `%s': \n " , kind , name ) ;
}
last_error_function = current_function_decl ;
}
}
/* Called by report_error_function to print out function name.
* Default may be overridden by language front - ends . */
void ( * print_error_function ) PROTO ( ( char * ) ) = default_print_error_function ;
/* Prints out, if necessary, the name of the current function
that caused an error . Called from all error and warning functions . */
void
report_error_function ( file )
char * file ;
{
struct file_stack * p ;
if ( need_error_newline )
{
fprintf ( stderr , " \n " ) ;
need_error_newline = 0 ;
}
( * print_error_function ) ( file ) ;
if ( input_file_stack & & input_file_stack - > next ! = 0
& & input_file_stack_tick ! = last_error_tick
& & file = = input_filename )
{
fprintf ( stderr , " In file included " ) ;
for ( p = input_file_stack - > next ; p ; p = p - > next )
{
fprintf ( stderr , " from %s:%d " , p - > name , p - > line ) ;
if ( p - > next )
fprintf ( stderr , " , \n " ) ;
}
fprintf ( stderr , " : \n " ) ;
last_error_tick = input_file_stack_tick ;
}
}
/* Print a message. */
static void
vmessage ( prefix , s , ap )
char * prefix ;
char * s ;
va_list ap ;
{
if ( prefix )
fprintf ( stderr , " %s: " , prefix ) ;
vfprintf ( stderr , s , ap ) ;
}
/* Print a message relevant to line LINE of file FILE. */
static void
v_message_with_file_and_line ( file , line , prefix , s , ap )
char * file ;
int line ;
char * prefix ;
char * s ;
va_list ap ;
{
if ( file )
fprintf ( stderr , " %s:%d: " , file , line ) ;
else
fprintf ( stderr , " %s: " , progname ) ;
vmessage ( prefix , s , ap ) ;
fputc ( ' \n ' , stderr ) ;
}
/* Print a message relevant to the given DECL. */
static void
v_message_with_decl ( decl , prefix , s , ap )
tree decl ;
char * prefix ;
char * s ;
va_list ap ;
{
1998-08-16 21:35:45 +04:00
char * p ;
1998-03-29 12:14:27 +04:00
fprintf ( stderr , " %s:%d: " ,
DECL_SOURCE_FILE ( decl ) , DECL_SOURCE_LINE ( decl ) ) ;
if ( prefix )
fprintf ( stderr , " %s: " , prefix ) ;
/* Do magic to get around lack of varargs support for insertion
of arguments into existing list . We know that the decl is first ;
we ass_u_me that it will be printed with " %s " . */
for ( p = s ; * p ; + + p )
{
if ( * p = = ' % ' )
{
if ( * ( p + 1 ) = = ' % ' )
+ + p ;
else
break ;
}
}
if ( p > s ) /* Print the left-hand substring. */
{
char fmt [ sizeof " %.255s " ] ;
long width = p - s ;
if ( width > 255L ) width = 255L ; /* arbitrary */
sprintf ( fmt , " %%.%lds " , width ) ;
fprintf ( stderr , fmt , s ) ;
}
if ( * p = = ' % ' ) /* Print the name. */
{
char * n = ( DECL_NAME ( decl )
? ( * decl_printable_name ) ( decl , 2 )
: " ((anonymous)) " ) ;
fputs ( n , stderr ) ;
while ( * p )
{
+ + p ;
1998-08-16 21:35:45 +04:00
if ( ISALPHA ( * ( p - 1 ) & 0xFF ) )
1998-03-29 12:14:27 +04:00
break ;
}
}
if ( * p ) /* Print the rest of the message. */
vmessage ( ( char * ) NULL , p , ap ) ;
fputc ( ' \n ' , stderr ) ;
}
/* Figure file and line of the given INSN. */
static void
file_and_line_for_asm ( insn , pfile , pline )
rtx insn ;
char * * pfile ;
int * pline ;
{
rtx body = PATTERN ( insn ) ;
rtx asmop ;
/* Find the (or one of the) ASM_OPERANDS in the insn. */
if ( GET_CODE ( body ) = = SET & & GET_CODE ( SET_SRC ( body ) ) = = ASM_OPERANDS )
asmop = SET_SRC ( body ) ;
else if ( GET_CODE ( body ) = = ASM_OPERANDS )
asmop = body ;
else if ( GET_CODE ( body ) = = PARALLEL
& & GET_CODE ( XVECEXP ( body , 0 , 0 ) ) = = SET )
asmop = SET_SRC ( XVECEXP ( body , 0 , 0 ) ) ;
else if ( GET_CODE ( body ) = = PARALLEL
& & GET_CODE ( XVECEXP ( body , 0 , 0 ) ) = = ASM_OPERANDS )
asmop = XVECEXP ( body , 0 , 0 ) ;
else
asmop = NULL ;
if ( asmop )
{
* pfile = ASM_OPERANDS_SOURCE_FILE ( asmop ) ;
* pline = ASM_OPERANDS_SOURCE_LINE ( asmop ) ;
}
else
{
* pfile = input_filename ;
* pline = lineno ;
}
}
/* Report an error at line LINE of file FILE. */
static void
v_error_with_file_and_line ( file , line , s , ap )
char * file ;
int line ;
char * s ;
va_list ap ;
{
count_error ( 0 ) ;
report_error_function ( file ) ;
v_message_with_file_and_line ( file , line , ( char * ) NULL , s , ap ) ;
}
void
error_with_file_and_line VPROTO ( ( char * file , int line , char * s , . . . ) )
{
# ifndef __STDC__
char * file ;
int line ;
char * s ;
# endif
va_list ap ;
VA_START ( ap , s ) ;
# ifndef __STDC__
file = va_arg ( ap , char * ) ;
line = va_arg ( ap , int ) ;
s = va_arg ( ap , char * ) ;
# endif
v_error_with_file_and_line ( file , line , s , ap ) ;
va_end ( ap ) ;
}
/* Report an error at the declaration DECL.
S is a format string which uses % s to substitute the declaration
name ; subsequent substitutions are a la printf . */
static void
v_error_with_decl ( decl , s , ap )
tree decl ;
char * s ;
va_list ap ;
{
count_error ( 0 ) ;
report_error_function ( DECL_SOURCE_FILE ( decl ) ) ;
v_message_with_decl ( decl , ( char * ) NULL , s , ap ) ;
}
void
error_with_decl VPROTO ( ( tree decl , char * s , . . . ) )
{
# ifndef __STDC__
tree decl ;
char * s ;
# endif
va_list ap ;
VA_START ( ap , s ) ;
# ifndef __STDC__
decl = va_arg ( ap , tree ) ;
s = va_arg ( ap , char * ) ;
# endif
v_error_with_decl ( decl , s , ap ) ;
va_end ( ap ) ;
}
/* Report an error at the line number of the insn INSN.
This is used only when INSN is an ` asm ' with operands ,
and each ASM_OPERANDS records its own source file and line . */
static void
v_error_for_asm ( insn , s , ap )
rtx insn ;
char * s ;
va_list ap ;
{
char * file ;
int line ;
count_error ( 0 ) ;
file_and_line_for_asm ( insn , & file , & line ) ;
report_error_function ( file ) ;
v_message_with_file_and_line ( file , line , ( char * ) NULL , s , ap ) ;
}
void
error_for_asm VPROTO ( ( rtx insn , char * s , . . . ) )
{
# ifndef __STDC__
rtx insn ;
char * s ;
# endif
va_list ap ;
VA_START ( ap , s ) ;
# ifndef __STDC__
insn = va_arg ( ap , rtx ) ;
s = va_arg ( ap , char * ) ;
# endif
v_error_for_asm ( insn , s , ap ) ;
va_end ( ap ) ;
}
/* Report an error at the current line number. */
static void
verror ( s , ap )
char * s ;
va_list ap ;
{
v_error_with_file_and_line ( input_filename , lineno , s , ap ) ;
}
void
error VPROTO ( ( char * s , . . . ) )
{
# ifndef __STDC__
char * s ;
# endif
va_list ap ;
VA_START ( ap , s ) ;
# ifndef __STDC__
s = va_arg ( ap , char * ) ;
# endif
verror ( s , ap ) ;
va_end ( ap ) ;
}
/* Report a fatal error at the current line number. */
static void
vfatal ( s , ap )
char * s ;
va_list ap ;
{
verror ( s , ap ) ;
exit ( FATAL_EXIT_CODE ) ;
}
void
fatal VPROTO ( ( char * s , . . . ) )
{
# ifndef __STDC__
char * s ;
# endif
va_list ap ;
VA_START ( ap , s ) ;
# ifndef __STDC__
s = va_arg ( ap , char * ) ;
# endif
vfatal ( s , ap ) ;
va_end ( ap ) ;
}
/* Report a warning at line LINE of file FILE. */
static void
v_warning_with_file_and_line ( file , line , s , ap )
char * file ;
int line ;
char * s ;
va_list ap ;
{
if ( count_error ( 1 ) )
{
report_error_function ( file ) ;
v_message_with_file_and_line ( file , line , " warning " , s , ap ) ;
}
}
void
warning_with_file_and_line VPROTO ( ( char * file , int line , char * s , . . . ) )
{
# ifndef __STDC__
char * file ;
int line ;
char * s ;
# endif
va_list ap ;
VA_START ( ap , s ) ;
# ifndef __STDC__
file = va_arg ( ap , char * ) ;
line = va_arg ( ap , int ) ;
s = va_arg ( ap , char * ) ;
# endif
v_warning_with_file_and_line ( file , line , s , ap ) ;
va_end ( ap ) ;
}
/* Report a warning at the declaration DECL.
S is a format string which uses % s to substitute the declaration
name ; subsequent substitutions are a la printf . */
static void
v_warning_with_decl ( decl , s , ap )
tree decl ;
char * s ;
va_list ap ;
{
if ( count_error ( 1 ) )
{
report_error_function ( DECL_SOURCE_FILE ( decl ) ) ;
v_message_with_decl ( decl , " warning " , s , ap ) ;
}
}
void
warning_with_decl VPROTO ( ( tree decl , char * s , . . . ) )
{
# ifndef __STDC__
tree decl ;
char * s ;
# endif
va_list ap ;
VA_START ( ap , s ) ;
# ifndef __STDC__
decl = va_arg ( ap , tree ) ;
s = va_arg ( ap , char * ) ;
# endif
v_warning_with_decl ( decl , s , ap ) ;
va_end ( ap ) ;
}
/* Report a warning at the line number of the insn INSN.
This is used only when INSN is an ` asm ' with operands ,
and each ASM_OPERANDS records its own source file and line . */
static void
v_warning_for_asm ( insn , s , ap )
rtx insn ;
char * s ;
va_list ap ;
{
if ( count_error ( 1 ) )
{
char * file ;
int line ;
file_and_line_for_asm ( insn , & file , & line ) ;
report_error_function ( file ) ;
v_message_with_file_and_line ( file , line , " warning " , s , ap ) ;
}
}
void
warning_for_asm VPROTO ( ( rtx insn , char * s , . . . ) )
{
# ifndef __STDC__
rtx insn ;
char * s ;
# endif
va_list ap ;
VA_START ( ap , s ) ;
# ifndef __STDC__
insn = va_arg ( ap , rtx ) ;
s = va_arg ( ap , char * ) ;
# endif
v_warning_for_asm ( insn , s , ap ) ;
va_end ( ap ) ;
}
/* Report a warning at the current line number. */
static void
vwarning ( s , ap )
char * s ;
va_list ap ;
{
v_warning_with_file_and_line ( input_filename , lineno , s , ap ) ;
}
void
warning VPROTO ( ( char * s , . . . ) )
{
# ifndef __STDC__
char * s ;
# endif
va_list ap ;
VA_START ( ap , s ) ;
# ifndef __STDC__
s = va_arg ( ap , char * ) ;
# endif
vwarning ( s , ap ) ;
va_end ( ap ) ;
}
/* These functions issue either warnings or errors depending on
- pedantic - errors . */
static void
vpedwarn ( s , ap )
char * s ;
va_list ap ;
{
if ( flag_pedantic_errors )
verror ( s , ap ) ;
else
vwarning ( s , ap ) ;
}
void
pedwarn VPROTO ( ( char * s , . . . ) )
{
# ifndef __STDC__
char * s ;
# endif
va_list ap ;
VA_START ( ap , s ) ;
# ifndef __STDC__
s = va_arg ( ap , char * ) ;
# endif
vpedwarn ( s , ap ) ;
va_end ( ap ) ;
}
static void
v_pedwarn_with_decl ( decl , s , ap )
tree decl ;
char * s ;
va_list ap ;
{
/* We don't want -pedantic-errors to cause the compilation to fail from
" errors " in system header files . Sometimes fixincludes can ' t fix what ' s
broken ( eg : unsigned char bitfields - fixing it may change the alignment
which will cause programs to mysteriously fail because the C library
or kernel uses the original layout ) . There ' s no point in issuing a
warning either , it ' s just unnecessary noise . */
if ( ! DECL_IN_SYSTEM_HEADER ( decl ) )
{
if ( flag_pedantic_errors )
v_error_with_decl ( decl , s , ap ) ;
else
v_warning_with_decl ( decl , s , ap ) ;
}
}
void
pedwarn_with_decl VPROTO ( ( tree decl , char * s , . . . ) )
{
# ifndef __STDC__
tree decl ;
char * s ;
# endif
va_list ap ;
VA_START ( ap , s ) ;
# ifndef __STDC__
decl = va_arg ( ap , tree ) ;
s = va_arg ( ap , char * ) ;
# endif
v_pedwarn_with_decl ( decl , s , ap ) ;
va_end ( ap ) ;
}
static void
v_pedwarn_with_file_and_line ( file , line , s , ap )
char * file ;
int line ;
char * s ;
va_list ap ;
{
if ( flag_pedantic_errors )
v_error_with_file_and_line ( file , line , s , ap ) ;
else
v_warning_with_file_and_line ( file , line , s , ap ) ;
}
void
pedwarn_with_file_and_line VPROTO ( ( char * file , int line , char * s , . . . ) )
{
# ifndef __STDC__
char * file ;
int line ;
char * s ;
# endif
va_list ap ;
VA_START ( ap , s ) ;
# ifndef __STDC__
file = va_arg ( ap , char * ) ;
line = va_arg ( ap , int ) ;
s = va_arg ( ap , char * ) ;
# endif
v_pedwarn_with_file_and_line ( file , line , s , ap ) ;
va_end ( ap ) ;
}
/* Apologize for not implementing some feature. */
static void
vsorry ( s , ap )
char * s ;
va_list ap ;
{
sorrycount + + ;
if ( input_filename )
fprintf ( stderr , " %s:%d: " , input_filename , lineno ) ;
else
fprintf ( stderr , " %s: " , progname ) ;
vmessage ( " sorry, not implemented " , s , ap ) ;
fputc ( ' \n ' , stderr ) ;
}
void
sorry VPROTO ( ( char * s , . . . ) )
{
# ifndef __STDC__
char * s ;
# endif
va_list ap ;
VA_START ( ap , s ) ;
# ifndef __STDC__
s = va_arg ( ap , char * ) ;
# endif
vsorry ( s , ap ) ;
va_end ( ap ) ;
}
/* Apologize for not implementing some feature, then quit. */
static void
v_really_sorry ( s , ap )
char * s ;
va_list ap ;
{
sorrycount + + ;
if ( input_filename )
fprintf ( stderr , " %s:%d: " , input_filename , lineno ) ;
else
fprintf ( stderr , " %s: " , progname ) ;
vmessage ( " sorry, not implemented " , s , ap ) ;
fatal ( " (fatal) \n " ) ;
}
void
really_sorry VPROTO ( ( char * s , . . . ) )
{
# ifndef __STDC__
char * s ;
# endif
va_list ap ;
VA_START ( ap , s ) ;
# ifndef __STDC__
s = va_arg ( ap , char * ) ;
# endif
v_really_sorry ( s , ap ) ;
va_end ( ap ) ;
}
/* More 'friendly' abort that prints the line and file.
config . h can # define abort fancy_abort if you like that sort of thing .
I don ' t think this is actually a good idea .
Other sorts of crashes will look a certain way .
It is a good thing if crashes from calling abort look the same way .
- - RMS */
void
fancy_abort ( )
{
fatal ( " internal gcc abort " ) ;
}
/* 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 . */
void
do_abort ( )
{
abort ( ) ;
}
/* When `malloc.c' is compiled with `rcheck' defined,
it calls this function to report clobberage . */
void
botch ( s )
1998-08-16 21:35:45 +04:00
char * s ;
1998-03-29 12:14:27 +04:00
{
abort ( ) ;
}
/* Same as `malloc' but report error if no memory available. */
char *
xmalloc ( size )
unsigned size ;
{
1998-08-16 21:35:45 +04:00
register char * value ;
if ( size = = 0 )
size = 1 ;
value = ( char * ) malloc ( size ) ;
if ( value = = 0 )
fatal ( " virtual memory exhausted " ) ;
return value ;
}
/* Same as `calloc' but report error if no memory available. */
char *
xcalloc ( size1 , size2 )
unsigned size1 , size2 ;
{
register char * value ;
if ( size1 = = 0 | | size2 = = 0 )
size1 = size2 = 1 ;
value = ( char * ) calloc ( size1 , size2 ) ;
if ( value = = 0 )
1998-03-29 12:14:27 +04:00
fatal ( " virtual memory exhausted " ) ;
return value ;
}
1998-08-16 21:35:45 +04:00
/* Same as `realloc' but report error if no memory available.
Also handle null PTR even if the vendor realloc gets it wrong . */
1998-03-29 12:14:27 +04:00
char *
xrealloc ( ptr , size )
char * ptr ;
int size ;
{
1998-08-16 21:35:45 +04:00
char * result ;
if ( size = = 0 )
size = 1 ;
result = ( ptr
? ( char * ) realloc ( ptr , size )
: ( char * ) malloc ( size ) ) ;
1998-03-29 12:14:27 +04:00
if ( ! result )
fatal ( " virtual memory exhausted " ) ;
1998-08-16 21:35:45 +04:00
1998-03-29 12:14:27 +04:00
return result ;
}
/* Same as `strdup' but report error if no memory available. */
char *
xstrdup ( s )
register char * s ;
{
register char * result = ( char * ) malloc ( strlen ( s ) + 1 ) ;
if ( ! result )
fatal ( " virtual memory exhausted " ) ;
strcpy ( result , s ) ;
return result ;
}
/* Return the logarithm of X, base 2, considering X unsigned,
if X is a power of 2. Otherwise , returns - 1.
This should be used via the ` exact_log2 ' macro . */
int
exact_log2_wide ( x )
register unsigned HOST_WIDE_INT x ;
{
register 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 ;
}
/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
If X is 0 , return - 1.
This should be used via the floor_log2 macro . */
int
floor_log2_wide ( x )
register unsigned HOST_WIDE_INT x ;
{
register int log = - 1 ;
while ( x ! = 0 )
log + + ,
x > > = 1 ;
return log ;
}
static int float_handler_set ;
int float_handled ;
jmp_buf float_handler ;
/* Signals actually come here. */
static void
float_signal ( signo )
/* If this is missing, some compilers complain. */
1998-08-16 21:35:45 +04:00
int signo ATTRIBUTE_UNUSED ;
1998-03-29 12:14:27 +04:00
{
if ( float_handled = = 0 )
abort ( ) ;
# if defined (USG) || defined (hpux)
signal ( SIGFPE , float_signal ) ; /* re-enable the signal catcher */
# endif
float_handled = 0 ;
signal ( SIGFPE , float_signal ) ;
longjmp ( float_handler , 1 ) ;
}
/* Specify where to longjmp to when a floating arithmetic error happens.
If HANDLER is 0 , it means don ' t handle the errors any more . */
void
set_float_handler ( handler )
jmp_buf handler ;
{
float_handled = ( handler ! = 0 ) ;
if ( handler )
bcopy ( ( char * ) handler , ( char * ) float_handler , sizeof ( float_handler ) ) ;
if ( float_handled & & ! float_handler_set )
{
signal ( SIGFPE , float_signal ) ;
float_handler_set = 1 ;
}
}
/* Specify, in HANDLER, where to longjmp to when a floating arithmetic
error happens , pushing the previous specification into OLD_HANDLER .
Return an indication of whether there was a previous handler in effect . */
int
push_float_handler ( handler , old_handler )
jmp_buf handler , old_handler ;
{
int was_handled = float_handled ;
float_handled = 1 ;
if ( was_handled )
bcopy ( ( char * ) float_handler , ( char * ) old_handler ,
sizeof ( float_handler ) ) ;
bcopy ( ( char * ) handler , ( char * ) float_handler , sizeof ( float_handler ) ) ;
return was_handled ;
}
/* Restore the previous specification of whether and where to longjmp to
when a floating arithmetic error happens . */
void
pop_float_handler ( handled , handler )
int handled ;
jmp_buf handler ;
{
float_handled = handled ;
if ( handled )
bcopy ( ( char * ) handler , ( char * ) float_handler , sizeof ( float_handler ) ) ;
}
/* Handler for SIGPIPE. */
static void
pipe_closed ( signo )
/* If this is missing, some compilers complain. */
1998-08-16 21:35:45 +04:00
int signo ATTRIBUTE_UNUSED ;
1998-03-29 12:14:27 +04:00
{
fatal ( " output pipe has been closed " ) ;
}
/* 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
1998-08-16 21:35:45 +04:00
our front ends , we strip off an ending of a period followed by
up to five characters . ( Java uses " .class " . ) */
1998-03-29 12:14:27 +04:00
void
strip_off_ending ( name , len )
char * name ;
int len ;
{
1998-08-16 21:35:45 +04:00
int i ;
for ( i = 2 ; i < 6 & & len > i ; i + + )
{
if ( name [ len - i ] = = ' . ' )
{
name [ len - i ] = ' \0 ' ;
break ;
}
}
1998-03-29 12:14:27 +04:00
}
/* Output a quoted string. */
void
output_quoted_string ( asm_file , string )
FILE * asm_file ;
char * string ;
{
1998-08-16 21:35:45 +04:00
# ifdef OUTPUT_QUOTED_STRING
OUTPUT_QUOTED_STRING ( asm_file , string ) ;
# else
1998-03-29 12:14:27 +04:00
char c ;
putc ( ' \" ' , asm_file ) ;
while ( ( c = * string + + ) ! = 0 )
{
if ( c = = ' \" ' | | c = = ' \\ ' )
putc ( ' \\ ' , asm_file ) ;
putc ( c , asm_file ) ;
}
putc ( ' \" ' , asm_file ) ;
1998-08-16 21:35:45 +04:00
# endif
1998-03-29 12:14:27 +04:00
}
/* Output a file name in the form wanted by System V. */
void
output_file_directive ( asm_file , input_name )
FILE * asm_file ;
char * input_name ;
{
int len = strlen ( input_name ) ;
char * na = input_name + len ;
/* NA gets INPUT_NAME sans directory names. */
while ( na > input_name )
{
if ( na [ - 1 ] = = ' / ' )
break ;
na - - ;
}
# ifdef ASM_OUTPUT_MAIN_SOURCE_FILENAME
ASM_OUTPUT_MAIN_SOURCE_FILENAME ( asm_file , na ) ;
# else
# ifdef ASM_OUTPUT_SOURCE_FILENAME
ASM_OUTPUT_SOURCE_FILENAME ( asm_file , na ) ;
# else
fprintf ( asm_file , " \t .file \t " ) ;
output_quoted_string ( asm_file , na ) ;
fputc ( ' \n ' , asm_file ) ;
# endif
# endif
}
/* Routine to build language identifier for object file. */
static void
output_lang_identify ( asm_out_file )
FILE * asm_out_file ;
{
int len = strlen ( lang_identify ( ) ) + sizeof ( " __gnu_compiled_ " ) + 1 ;
char * s = ( char * ) alloca ( len ) ;
sprintf ( s , " __gnu_compiled_%s " , lang_identify ( ) ) ;
ASM_OUTPUT_LABEL ( asm_out_file , s ) ;
}
/* Routine to open a dump file. */
1998-08-16 21:35:45 +04:00
static void
open_dump_file ( suffix , function_name )
char * suffix ;
char * function_name ;
{
char * dumpname ;
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
TIMEVAR
( dump_time ,
{
dumpname = ( char * ) xmalloc ( strlen ( dump_base_name ) + strlen ( suffix ) + 1 ) ;
if ( rtl_dump_file ! = NULL )
fclose ( rtl_dump_file ) ;
strcpy ( dumpname , dump_base_name ) ;
strcat ( dumpname , suffix ) ;
rtl_dump_file = fopen ( dumpname , " a " ) ;
if ( rtl_dump_file = = NULL )
pfatal_with_name ( dumpname ) ;
free ( dumpname ) ;
if ( function_name )
fprintf ( rtl_dump_file , " \n ;; Function %s \n \n " , function_name ) ;
} ) ;
return ;
}
/* Routine to close a dump file. */
static void
close_dump_file ( func , insns )
void ( * func ) PROTO ( ( FILE * , rtx ) ) ;
rtx insns ;
{
TIMEVAR
( dump_time ,
{
if ( func )
func ( rtl_dump_file , insns ) ;
fflush ( rtl_dump_file ) ;
fclose ( rtl_dump_file ) ;
rtl_dump_file = NULL ;
} ) ;
return ;
}
/* Routine to dump rtl into a file. */
static void
dump_rtl ( suffix , decl , func , insns )
1998-03-29 12:14:27 +04:00
char * suffix ;
1998-08-16 21:35:45 +04:00
tree decl ;
void ( * func ) PROTO ( ( FILE * , rtx ) ) ;
rtx insns ;
{
open_dump_file ( suffix , decl_printable_name ( decl , 2 ) ) ;
close_dump_file ( func , insns ) ;
}
/* Routine to empty a dump file. */
static void
clean_dump_file ( suffix )
char * suffix ;
1998-03-29 12:14:27 +04:00
{
1998-08-16 21:35:45 +04:00
char * dumpname ;
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
dumpname = ( char * ) xmalloc ( strlen ( dump_base_name ) + strlen ( suffix ) + 1 ) ;
strcpy ( dumpname , dump_base_name ) ;
1998-03-29 12:14:27 +04:00
strcat ( dumpname , suffix ) ;
1998-08-16 21:35:45 +04:00
rtl_dump_file = fopen ( dumpname , " w " ) ;
if ( rtl_dump_file = = NULL )
pfatal_with_name ( dumpname ) ;
free ( dumpname ) ;
fclose ( rtl_dump_file ) ;
rtl_dump_file = NULL ;
return ;
1998-03-29 12:14:27 +04:00
}
1998-08-16 21:35:45 +04:00
1998-03-29 12:14:27 +04:00
/* Compile an entire file of output from cpp, named NAME.
Write a file of assembly output and various debugging dumps . */
static void
compile_file ( name )
char * name ;
{
tree globals ;
int start_time ;
int name_specified = name ! = 0 ;
if ( dump_base_name = = 0 )
dump_base_name = name ? name : " gccdump " ;
parse_time = 0 ;
varconst_time = 0 ;
integration_time = 0 ;
jump_time = 0 ;
cse_time = 0 ;
1998-08-16 21:35:45 +04:00
gcse_time = 0 ;
1998-03-29 12:14:27 +04:00
loop_time = 0 ;
cse2_time = 0 ;
branch_prob_time = 0 ;
flow_time = 0 ;
combine_time = 0 ;
regmove_time = 0 ;
sched_time = 0 ;
local_alloc_time = 0 ;
global_alloc_time = 0 ;
sched2_time = 0 ;
1998-08-16 21:35:45 +04:00
# ifdef DELAY_SLOTS
1998-03-29 12:14:27 +04:00
dbr_sched_time = 0 ;
1998-08-16 21:35:45 +04:00
# endif
1998-03-29 12:14:27 +04:00
shorten_branch_time = 0 ;
stack_reg_time = 0 ;
final_time = 0 ;
symout_time = 0 ;
dump_time = 0 ;
/* Initialize data in various passes. */
init_obstacks ( ) ;
init_tree_codes ( ) ;
1998-08-16 21:35:45 +04:00
name = init_parse ( name ) ;
1998-03-29 12:14:27 +04:00
init_rtl ( ) ;
init_emit_once ( debug_info_level = = DINFO_LEVEL_NORMAL
| | debug_info_level = = DINFO_LEVEL_VERBOSE
| | flag_test_coverage ) ;
init_regs ( ) ;
init_decl_processing ( ) ;
init_optabs ( ) ;
init_stmt ( ) ;
init_expmed ( ) ;
init_expr_once ( ) ;
init_loop ( ) ;
init_reload ( ) ;
1998-08-16 21:35:45 +04:00
init_alias_once ( ) ;
1998-03-29 12:14:27 +04:00
if ( flag_caller_saves )
init_caller_save ( ) ;
/* 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 )
pfatal_with_name ( aux_info_file_name ) ;
}
1998-08-16 21:35:45 +04:00
/* Clear the dump files file. */
1998-03-29 12:14:27 +04:00
if ( rtl_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .rtl " ) ;
1998-03-29 12:14:27 +04:00
if ( jump_opt_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .jump " ) ;
if ( addressof_dump )
clean_dump_file ( " .addressof " ) ;
1998-03-29 12:14:27 +04:00
if ( cse_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .cse " ) ;
1998-03-29 12:14:27 +04:00
if ( loop_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .loop " ) ;
1998-03-29 12:14:27 +04:00
if ( cse2_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .cse2 " ) ;
1998-03-29 12:14:27 +04:00
if ( branch_prob_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .bp " ) ;
1998-03-29 12:14:27 +04:00
if ( flow_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .flow " ) ;
1998-03-29 12:14:27 +04:00
if ( combine_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .combine " ) ;
1998-03-29 12:14:27 +04:00
if ( regmove_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .regmove " ) ;
1998-03-29 12:14:27 +04:00
if ( sched_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .sched " ) ;
1998-03-29 12:14:27 +04:00
if ( local_reg_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .lreg " ) ;
1998-03-29 12:14:27 +04:00
if ( global_reg_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .greg " ) ;
1998-03-29 12:14:27 +04:00
if ( sched2_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .sched2 " ) ;
1998-03-29 12:14:27 +04:00
if ( jump2_opt_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .jump2 " ) ;
# ifdef DELAY_SLOTS
1998-03-29 12:14:27 +04:00
if ( dbr_sched_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .dbr " ) ;
# endif
if ( gcse_dump )
clean_dump_file ( " .gcse " ) ;
1998-03-29 12:14:27 +04:00
# ifdef STACK_REGS
if ( stack_reg_dump )
1998-08-16 21:35:45 +04:00
clean_dump_file ( " .stack " ) ;
# endif
# ifdef MACHINE_DEPENDENT_REORG
if ( mach_dep_reorg_dump )
clean_dump_file ( " .mach " ) ;
1998-03-29 12:14:27 +04:00
# endif
/* Open assembler code output file. */
if ( ! name_specified & & asm_file_name = = 0 )
asm_out_file = stdout ;
else
{
int len = strlen ( dump_base_name ) ;
register char * dumpname = ( char * ) xmalloc ( len + 6 ) ;
strcpy ( dumpname , dump_base_name ) ;
strip_off_ending ( dumpname , len ) ;
strcat ( dumpname , " .s " ) ;
if ( asm_file_name = = 0 )
{
asm_file_name = ( char * ) xmalloc ( strlen ( dumpname ) + 1 ) ;
strcpy ( asm_file_name , dumpname ) ;
}
if ( ! strcmp ( asm_file_name , " - " ) )
asm_out_file = stdout ;
else
asm_out_file = fopen ( asm_file_name , " w " ) ;
if ( asm_out_file = = 0 )
pfatal_with_name ( asm_file_name ) ;
}
# ifdef IO_BUFFER_SIZE
setvbuf ( asm_out_file , ( char * ) xmalloc ( IO_BUFFER_SIZE ) ,
_IOFBF , IO_BUFFER_SIZE ) ;
# endif
input_filename = name ;
/* Put an entry on the input file stack for the main input file. */
input_file_stack
= ( struct file_stack * ) xmalloc ( sizeof ( struct file_stack ) ) ;
input_file_stack - > next = 0 ;
input_file_stack - > name = input_filename ;
/* Perform language-specific initialization.
This may set main_input_filename . */
lang_init ( ) ;
/* If the input doesn't start with a #line, use the input name
as the official input file name . */
if ( main_input_filename = = 0 )
main_input_filename = name ;
1998-08-16 21:35:45 +04:00
ASM_FILE_START ( asm_out_file ) ;
1998-03-29 12:14:27 +04:00
# ifdef ASM_COMMENT_START
1998-08-16 21:35:45 +04:00
if ( flag_verbose_asm )
{
/* Print the list of options in effect. */
print_version ( asm_out_file , ASM_COMMENT_START ) ;
print_switch_values ( asm_out_file , 0 , MAX_LINE ,
1998-03-29 12:14:27 +04:00
ASM_COMMENT_START , " " , " \n " ) ;
1998-08-16 21:35:45 +04:00
/* Add a blank line here so it appears in assembler output but not
screen output . */
fprintf ( asm_out_file , " \n " ) ;
1998-03-29 12:14:27 +04:00
}
1998-08-16 21:35:45 +04:00
# endif
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
/* Output something to inform GDB that this compilation was by GCC. */
1998-03-29 12:14:27 +04:00
# ifndef ASM_IDENTIFY_GCC
1998-08-16 21:35:45 +04:00
fprintf ( asm_out_file , " gcc2_compiled.: \n " ) ;
1998-03-29 12:14:27 +04:00
# else
1998-08-16 21:35:45 +04:00
ASM_IDENTIFY_GCC ( asm_out_file ) ;
1998-03-29 12:14:27 +04:00
# endif
/* Output something to identify which front-end produced this file. */
# ifdef ASM_IDENTIFY_LANGUAGE
ASM_IDENTIFY_LANGUAGE ( asm_out_file ) ;
# endif
# ifndef ASM_OUTPUT_SECTION_NAME
if ( flag_function_sections )
{
warning ( " -ffunction-sections not supported for this target. " ) ;
flag_function_sections = 0 ;
}
# endif
if ( flag_function_sections
& & ( profile_flag | | profile_block_flag ) )
{
warning ( " -ffunction-sections disabled; it makes profiling impossible. " ) ;
flag_function_sections = 0 ;
}
if ( flag_function_sections & & write_symbols ! = NO_DEBUG )
warning ( " -ffunction-sections may affect debugging on some targets. " ) ;
1998-08-16 21:35:45 +04:00
/* ??? Note: There used to be a conditional here
to call assemble_zeros without fail if DBX_DEBUGGING_INFO is defined .
This was to guarantee separation between gcc_compiled . and
the first function , for the sake of dbx on Suns .
However , having the extra zero here confused the Emacs
code for unexec , and might confuse other programs too .
Therefore , I took out that change .
In future versions we should find another way to solve
that dbx problem . - - rms , 23 May 93. */
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
/* Don't let the first function fall at the same address
as gcc_compiled . , if profiling . */
if ( profile_flag | | profile_block_flag )
{
/* It's best if we can write a nop here since some
assemblers don ' t tolerate zeros in the text section . */
if ( insn_template [ CODE_FOR_nop ] ! = 0 )
output_asm_insn ( insn_template [ CODE_FOR_nop ] , NULL_PTR ) ;
else
1998-03-29 12:14:27 +04:00
assemble_zeros ( UNITS_PER_WORD ) ;
}
/* If dbx symbol table desired, initialize writing it
and output the predefined types . */
# if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if ( write_symbols = = DBX_DEBUG | | write_symbols = = XCOFF_DEBUG )
TIMEVAR ( symout_time , dbxout_init ( asm_out_file , main_input_filename ,
getdecls ( ) ) ) ;
# endif
# ifdef SDB_DEBUGGING_INFO
if ( write_symbols = = SDB_DEBUG )
TIMEVAR ( symout_time , sdbout_init ( asm_out_file , main_input_filename ,
getdecls ( ) ) ) ;
# endif
# ifdef DWARF_DEBUGGING_INFO
if ( write_symbols = = DWARF_DEBUG )
TIMEVAR ( symout_time , dwarfout_init ( asm_out_file , main_input_filename ) ) ;
# endif
# ifdef DWARF2_UNWIND_INFO
if ( dwarf2out_do_frame ( ) )
dwarf2out_frame_init ( ) ;
# endif
# ifdef DWARF2_DEBUGGING_INFO
if ( write_symbols = = DWARF2_DEBUG )
TIMEVAR ( symout_time , dwarf2out_init ( asm_out_file , main_input_filename ) ) ;
# endif
/* Initialize yet another pass. */
1998-08-16 21:35:45 +04:00
init_final ( main_input_filename ) ;
1998-03-29 12:14:27 +04:00
init_branch_prob ( dump_base_name ) ;
start_time = get_run_time ( ) ;
/* Call the parser, which parses the entire file
( calling rest_of_compilation for each function ) . */
if ( yyparse ( ) ! = 0 )
{
if ( errorcount = = 0 )
fprintf ( stderr , " Errors detected in input file (your bison.simple is out of date) " ) ;
/* In case there were missing closebraces,
get us back to the global binding level . */
while ( ! global_bindings_p ( ) )
poplevel ( 0 , 0 , 0 ) ;
}
output_func_start_profiler ( ) ;
/* Compilation is now finished except for writing
what ' s left of the symbol table output . */
parse_time + = get_run_time ( ) - start_time ;
parse_time - = integration_time ;
parse_time - = varconst_time ;
globals = getdecls ( ) ;
/* 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 . */
{
int len = list_length ( globals ) ;
tree * vec = ( tree * ) alloca ( sizeof ( tree ) * len ) ;
int i ;
tree decl ;
int reconsider = 1 ;
/* Process the decls in reverse order--earliest first.
Put them into VEC from back to front , then take out from front . */
for ( i = 0 , decl = globals ; i < len ; i + + , decl = TREE_CHAIN ( decl ) )
vec [ len - i - 1 ] = decl ;
for ( i = 0 ; i < len ; i + + )
{
decl = vec [ i ] ;
/* We're not deferring this any longer. */
DECL_DEFER_OUTPUT ( decl ) = 0 ;
if ( TREE_CODE ( decl ) = = VAR_DECL & & DECL_SIZE ( decl ) = = 0
& & incomplete_decl_finalize_hook ! = 0 )
( * incomplete_decl_finalize_hook ) ( decl ) ;
}
/* 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 . */
while ( reconsider )
{
reconsider = 0 ;
for ( i = 0 ; i < len ; i + + )
{
decl = vec [ i ] ;
if ( TREE_ASM_WRITTEN ( decl ) | | DECL_EXTERNAL ( decl ) )
continue ;
/* Don't write out static consts, unless we still need them.
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 .
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 .
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 .
? ? ? 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 . */
if ( TREE_CODE ( decl ) = = VAR_DECL & & TREE_STATIC ( decl )
& & ( ! TREE_READONLY ( decl )
| | TREE_PUBLIC ( decl )
| | ( ! optimize & & flag_keep_static_consts )
| | TREE_SYMBOL_REFERENCED ( DECL_ASSEMBLER_NAME ( decl ) ) ) )
{
reconsider = 1 ;
rest_of_decl_compilation ( decl , NULL_PTR , 1 , 1 ) ;
}
if ( TREE_CODE ( decl ) = = FUNCTION_DECL
& & DECL_INITIAL ( decl ) ! = 0
& & DECL_SAVED_INSNS ( decl ) ! = 0
& & ( flag_keep_inline_functions
| | TREE_PUBLIC ( decl )
| | TREE_SYMBOL_REFERENCED ( DECL_ASSEMBLER_NAME ( decl ) ) ) )
{
reconsider = 1 ;
temporary_allocation ( ) ;
output_inline_function ( decl ) ;
permanent_allocation ( 1 ) ;
}
}
}
/* Now that all possible functions have been output, we can dump
the exception table . */
output_exception_table ( ) ;
for ( i = 0 ; i < len ; i + + )
{
decl = vec [ i ] ;
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 . */
DECL_RTL ( decl ) = NULL ;
/* 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
| | TREE_SYMBOL_REFERENCED ( DECL_ASSEMBLER_NAME ( decl ) ) )
& & DECL_INITIAL ( decl ) = = 0
& & DECL_EXTERNAL ( decl )
& & ! DECL_ARTIFICIAL ( decl )
& & ! TREE_PUBLIC ( decl ) )
{
pedwarn_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
& & ( ( TREE_CODE ( decl ) = = FUNCTION_DECL & & ! DECL_INLINE ( decl ) )
| | ( 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 " ) ;
# ifdef SDB_DEBUGGING_INFO
/* The COFF linker can move initialized global vars to the end.
And that can screw up the symbol ordering .
By putting the symbols in that order to begin with ,
we avoid a problem . mcsun ! unido ! fauern ! tumuc ! pes @ uunet . uu . net . */
if ( write_symbols = = SDB_DEBUG & & TREE_CODE ( decl ) = = VAR_DECL
& & TREE_PUBLIC ( decl ) & & DECL_INITIAL ( decl )
& & ! DECL_EXTERNAL ( decl )
& & DECL_RTL ( decl ) ! = 0 )
TIMEVAR ( symout_time , sdbout_symbol ( decl , 0 ) ) ;
/* Output COFF information for non-global
file - scope initialized variables . */
if ( write_symbols = = SDB_DEBUG
& & TREE_CODE ( decl ) = = VAR_DECL
& & DECL_INITIAL ( decl )
& & ! DECL_EXTERNAL ( decl )
& & DECL_RTL ( decl ) ! = 0
& & GET_CODE ( DECL_RTL ( decl ) ) = = MEM )
TIMEVAR ( symout_time , sdbout_toplevel_data ( decl ) ) ;
# endif /* SDB_DEBUGGING_INFO */
# ifdef DWARF_DEBUGGING_INFO
/* Output DWARF information for file-scope tentative data object
declarations , file - scope ( extern ) function declarations ( which
had no corresponding body ) and file - scope tagged type declarations
and definitions which have not yet been forced out . */
if ( write_symbols = = DWARF_DEBUG
& & ( TREE_CODE ( decl ) ! = FUNCTION_DECL | | ! DECL_INITIAL ( decl ) ) )
TIMEVAR ( symout_time , dwarfout_file_scope_decl ( decl , 1 ) ) ;
# endif
# ifdef DWARF2_DEBUGGING_INFO
/* Output DWARF2 information for file-scope tentative data object
declarations , file - scope ( extern ) function declarations ( which
had no corresponding body ) and file - scope tagged type declarations
and definitions which have not yet been forced out . */
if ( write_symbols = = DWARF2_DEBUG
& & ( TREE_CODE ( decl ) ! = FUNCTION_DECL | | ! DECL_INITIAL ( decl ) ) )
TIMEVAR ( symout_time , dwarf2out_decl ( decl ) ) ;
# endif
}
}
/* Write out any pending weak symbol declarations. */
weak_finish ( ) ;
/* Do dbx symbols */
# if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if ( write_symbols = = DBX_DEBUG | | write_symbols = = XCOFF_DEBUG )
TIMEVAR ( symout_time ,
{
dbxout_finish ( asm_out_file , main_input_filename ) ;
} ) ;
# endif
# ifdef DWARF_DEBUGGING_INFO
if ( write_symbols = = DWARF_DEBUG )
TIMEVAR ( symout_time ,
{
dwarfout_finish ( ) ;
} ) ;
# endif
# ifdef DWARF2_UNWIND_INFO
if ( dwarf2out_do_frame ( ) )
dwarf2out_frame_finish ( ) ;
# endif
# ifdef DWARF2_DEBUGGING_INFO
if ( write_symbols = = DWARF2_DEBUG )
TIMEVAR ( symout_time ,
{
dwarf2out_finish ( ) ;
} ) ;
# endif
/* Output some stuff at end of file if nec. */
1998-08-16 21:35:45 +04:00
end_final ( dump_base_name ) ;
if ( branch_prob_dump )
open_dump_file ( " .bp " , NULL ) ;
TIMEVAR ( dump_time , end_branch_prob ( rtl_dump_file ) ) ;
if ( branch_prob_dump )
close_dump_file ( NULL , NULL_RTX ) ;
1998-03-29 12:14:27 +04:00
# ifdef ASM_FILE_END
1998-08-16 21:35:45 +04:00
ASM_FILE_END ( asm_out_file ) ;
1998-03-29 12:14:27 +04:00
# endif
/* Language-specific end of compilation actions. */
lang_finish ( ) ;
/* Close the dump files. */
if ( flag_gen_aux_info )
{
fclose ( aux_info_file ) ;
if ( errorcount )
unlink ( aux_info_file_name ) ;
}
if ( combine_dump )
{
1998-08-16 21:35:45 +04:00
open_dump_file ( " .combine " , NULL ) ;
TIMEVAR ( dump_time , dump_combine_total_stats ( rtl_dump_file ) ) ;
close_dump_file ( NULL , NULL_RTX ) ;
1998-03-29 12:14:27 +04:00
}
1998-08-16 21:35:45 +04: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 . */
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
finish_parse ( ) ;
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
if ( ferror ( asm_out_file ) ! = 0 | | fclose ( asm_out_file ) ! = 0 )
fatal_io_error ( asm_file_name ) ;
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
/* Print the times. */
1998-03-29 12:14:27 +04:00
if ( ! quiet_flag )
{
fprintf ( stderr , " \n " ) ;
print_time ( " parse " , parse_time ) ;
1998-08-16 21:35:45 +04:00
print_time ( " integration " , integration_time ) ;
print_time ( " jump " , jump_time ) ;
print_time ( " cse " , cse_time ) ;
print_time ( " gcse " , gcse_time ) ;
print_time ( " loop " , loop_time ) ;
print_time ( " cse2 " , cse2_time ) ;
print_time ( " branch-prob " , branch_prob_time ) ;
print_time ( " flow " , flow_time ) ;
print_time ( " combine " , combine_time ) ;
print_time ( " regmove " , regmove_time ) ;
print_time ( " sched " , sched_time ) ;
print_time ( " local-alloc " , local_alloc_time ) ;
print_time ( " global-alloc " , global_alloc_time ) ;
print_time ( " sched2 " , sched2_time ) ;
# ifdef DELAY_SLOTS
print_time ( " dbranch " , dbr_sched_time ) ;
# endif
print_time ( " shorten-branch " , shorten_branch_time ) ;
print_time ( " stack-reg " , stack_reg_time ) ;
print_time ( " final " , final_time ) ;
print_time ( " varconst " , varconst_time ) ;
print_time ( " symout " , symout_time ) ;
print_time ( " dump " , dump_time ) ;
1998-03-29 12:14:27 +04:00
}
}
/* This is called from various places for FUNCTION_DECL, VAR_DECL,
and TYPE_DECL nodes .
This does nothing for local ( non - static ) variables .
Otherwise , it sets up the RTL and outputs any assembler code
( label definition , storage allocation and initialization ) .
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 . */
void
rest_of_decl_compilation ( decl , asmspec , top_level , at_end )
tree decl ;
char * asmspec ;
int top_level ;
int at_end ;
{
/* Declarations of variables, and of functions defined elsewhere. */
/* 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)
# endif
/* 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 ( varconst_time ,
{
make_decl_rtl ( decl , asmspec , top_level ) ;
/* Initialized extern variable exists to be replaced
with its value , or represents something that will be
output in another file . */
if ( ! ( TREE_CODE ( decl ) = = VAR_DECL
& & DECL_EXTERNAL ( decl ) & & TREE_READONLY ( decl )
& & DECL_INITIAL ( decl ) ! = 0
& & DECL_INITIAL ( decl ) ! = error_mark_node ) )
/* Don't output anything
when a tentative file - scope definition is seen .
But at end of compilation , do output code for them . */
if ( ! ( ! at_end & & top_level
& & ( DECL_INITIAL ( decl ) = = 0
| | DECL_INITIAL ( decl ) = = error_mark_node ) ) )
assemble_variable ( decl , top_level , at_end , 0 ) ;
1998-08-16 21:35:45 +04:00
if ( decl = = last_assemble_variable_decl )
1998-03-29 12:14:27 +04:00
{
ASM_FINISH_DECLARE_OBJECT ( asm_out_file , decl ,
top_level , at_end ) ;
}
} ) ;
else if ( DECL_REGISTER ( decl ) & & asmspec ! = 0 )
{
if ( decode_reg_name ( asmspec ) > = 0 )
{
DECL_RTL ( decl ) = 0 ;
make_decl_rtl ( decl , asmspec , top_level ) ;
}
else
error ( " invalid register name `%s' for register variable " , asmspec ) ;
}
# 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 ( symout_time , dbxout_symbol ( decl , 0 ) ) ;
# endif
# ifdef SDB_DEBUGGING_INFO
else if ( write_symbols = = SDB_DEBUG & & top_level
& & TREE_CODE ( decl ) = = TYPE_DECL )
TIMEVAR ( symout_time , sdbout_symbol ( decl , 0 ) ) ;
# endif
}
/* Called after finishing a record, union or enumeral type. */
void
rest_of_type_compilation ( type , toplev )
tree type ;
int toplev ;
{
# if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if ( write_symbols = = DBX_DEBUG | | write_symbols = = XCOFF_DEBUG )
TIMEVAR ( symout_time , dbxout_symbol ( TYPE_STUB_DECL ( type ) , ! toplev ) ) ;
# endif
# ifdef SDB_DEBUGGING_INFO
if ( write_symbols = = SDB_DEBUG )
TIMEVAR ( symout_time , sdbout_symbol ( TYPE_STUB_DECL ( type ) , ! toplev ) ) ;
# endif
}
/* This is called from finish_function (within yyparse)
after each top - level definition is parsed .
It is supposed to compile that function or variable
and output the assembler code for it .
After we return , the tree storage is freed . */
void
rest_of_compilation ( decl )
tree decl ;
{
register rtx insns ;
int start_time = get_run_time ( ) ;
int tem ;
/* Nonzero if we have saved the original DECL_INITIAL of the function,
to be restored after we finish compiling the function
( for use when compiling inline calls to this function ) . */
tree saved_block_tree = 0 ;
/* Likewise, for DECL_ARGUMENTS. */
tree saved_arguments = 0 ;
int failure = 0 ;
/* If we are reconsidering an inline function
at the end of compilation , skip the stuff for making it inline . */
if ( DECL_SAVED_INSNS ( decl ) = = 0 )
{
1998-08-16 21:35:45 +04:00
int inlinable = 0 ;
1998-03-29 12:14:27 +04:00
char * lose ;
/* If requested, consider whether to make this function inline. */
if ( DECL_INLINE ( decl ) | | flag_inline_functions )
TIMEVAR ( integration_time ,
{
lose = function_cannot_inline_p ( decl ) ;
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 . */
1998-08-16 21:35:45 +04:00
inlinable = DECL_INLINE ( decl ) = 1 ;
1998-03-29 12:14:27 +04:00
} ) ;
insns = get_insns ( ) ;
/* Dump the rtl code if we are dumping rtl. */
if ( rtl_dump )
1998-08-16 21:35:45 +04:00
{
open_dump_file ( " .rtl " , decl_printable_name ( decl , 2 ) ) ;
if ( DECL_SAVED_INSNS ( decl ) )
fprintf ( rtl_dump_file , " ;; (integrable) \n \n " ) ;
close_dump_file ( print_rtl , insns ) ;
}
1998-03-29 12:14:27 +04:00
/* If we can, defer compiling inlines until EOF.
save_for_inline_copying can be extremely expensive . */
1998-08-16 21:35:45 +04:00
if ( inlinable & & ! decl_function_context ( decl ) )
1998-03-29 12:14:27 +04:00
DECL_DEFER_OUTPUT ( decl ) = 1 ;
/* 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 . We cannot defer
functions containing nested functions since the nested function
1998-08-16 21:35:45 +04:00
data is in our non - saved obstack . We cannot defer nested
functions for the same reason . */
/* If this is a nested inline, remove ADDRESSOF now so we can
finish compiling ourselves . Otherwise , wait until EOF .
We have to do this because the purge_addressof transformation
changes the DECL_RTL for many variables , which confuses integrate . */
if ( inlinable )
{
if ( decl_function_context ( decl ) )
purge_addressof ( insns ) ;
else
DECL_DEFER_OUTPUT ( decl ) = 1 ;
}
1998-03-29 12:14:27 +04:00
if ( ! current_function_contains_functions
& & ( DECL_DEFER_OUTPUT ( decl )
| | ( DECL_INLINE ( decl )
& & ( ( ! TREE_PUBLIC ( decl ) & & ! TREE_ADDRESSABLE ( decl )
& & ! flag_keep_inline_functions )
| | DECL_EXTERNAL ( decl ) ) ) ) )
{
DECL_DEFER_OUTPUT ( decl ) = 1 ;
/* If -Wreturn-type, we have to do a bit of compilation.
However , if we just fall through we will call
save_for_inline_copying ( ) which results in excessive
memory use . Instead , we just want to call
jump_optimize ( ) 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 . And , we set optimize
to zero to keep jump_optimize from working too hard . */
if ( warn_return_type )
{
int saved_optimize = optimize ;
optimize = 0 ;
find_exception_handler_labels ( ) ;
1998-08-16 21:35:45 +04:00
jump_optimize ( get_insns ( ) , ! JUMP_CROSS_JUMP , ! JUMP_NOOP_MOVES ,
! JUMP_AFTER_REGSCAN ) ;
1998-03-29 12:14:27 +04:00
optimize = saved_optimize ;
}
# ifdef DWARF_DEBUGGING_INFO
/* Generate the DWARF info for the "abstract" instance
of a function which we may later generate inlined and / or
out - of - line instances of . */
if ( write_symbols = = DWARF_DEBUG )
{
set_decl_abstract_flags ( decl , 1 ) ;
TIMEVAR ( symout_time , dwarfout_file_scope_decl ( decl , 0 ) ) ;
set_decl_abstract_flags ( decl , 0 ) ;
}
# endif
# ifdef DWARF2_DEBUGGING_INFO
/* Generate the DWARF2 info for the "abstract" instance
of a function which we may later generate inlined and / or
out - of - line instances of . */
if ( write_symbols = = DWARF2_DEBUG )
{
set_decl_abstract_flags ( decl , 1 ) ;
TIMEVAR ( symout_time , dwarf2out_decl ( decl ) ) ;
set_decl_abstract_flags ( decl , 0 ) ;
}
# endif
TIMEVAR ( integration_time , save_for_inline_nocopy ( decl ) ) ;
1998-08-16 21:35:45 +04:00
RTX_INTEGRATED_P ( DECL_SAVED_INSNS ( decl ) ) = inlinable ;
1998-03-29 12:14:27 +04:00
goto exit_rest_of_compilation ;
}
/* If we have to compile the function now, save its rtl and subdecls
so that its compilation will not affect what others get . */
1998-08-16 21:35:45 +04:00
if ( inlinable | | DECL_DEFER_OUTPUT ( decl ) )
1998-03-29 12:14:27 +04:00
{
# ifdef DWARF_DEBUGGING_INFO
/* Generate the DWARF info for the "abstract" instance of
a function which we will generate an out - of - line instance
of almost immediately ( and which we may also later generate
various inlined instances of ) . */
if ( write_symbols = = DWARF_DEBUG )
{
set_decl_abstract_flags ( decl , 1 ) ;
TIMEVAR ( symout_time , dwarfout_file_scope_decl ( decl , 0 ) ) ;
set_decl_abstract_flags ( decl , 0 ) ;
}
# endif
# ifdef DWARF2_DEBUGGING_INFO
/* Generate the DWARF2 info for the "abstract" instance of
a function which we will generate an out - of - line instance
of almost immediately ( and which we may also later generate
various inlined instances of ) . */
if ( write_symbols = = DWARF2_DEBUG )
{
set_decl_abstract_flags ( decl , 1 ) ;
TIMEVAR ( symout_time , dwarf2out_decl ( decl ) ) ;
set_decl_abstract_flags ( decl , 0 ) ;
}
# endif
saved_block_tree = DECL_INITIAL ( decl ) ;
saved_arguments = DECL_ARGUMENTS ( decl ) ;
TIMEVAR ( integration_time , save_for_inline_copying ( decl ) ) ;
1998-08-16 21:35:45 +04:00
RTX_INTEGRATED_P ( DECL_SAVED_INSNS ( decl ) ) = inlinable ;
1998-03-29 12:14:27 +04:00
}
/* If specified extern inline but we aren't inlining it, we are
done . */
if ( DECL_INLINE ( decl ) & & DECL_EXTERNAL ( decl ) )
goto exit_rest_of_compilation ;
}
if ( ! DECL_DEFER_OUTPUT ( decl ) )
TREE_ASM_WRITTEN ( decl ) = 1 ;
/* 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 . */
rtx_equal_function_value_matters = 0 ;
/* Don't return yet if -Wreturn-type; we need to do jump_optimize. */
if ( ( rtl_dump_and_exit | | flag_syntax_only ) & & ! warn_return_type )
{
goto exit_rest_of_compilation ;
}
1998-08-16 21:35:45 +04:00
/* Emit code to get eh context, if needed. */
emit_eh_context ( ) ;
1998-03-29 12:14:27 +04: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
/* From now on, allocate rtl in current_obstack, not in saveable_obstack.
Note that that may have been done above , in save_for_inline_copying .
The call to resume_temporary_allocation near the end of this function
goes back to the usual state of affairs . This must be done after
we ' ve built up any unwinders for exception handling , and done
the FINALIZE_PIC work , if necessary . */
rtl_in_current_obstack ( ) ;
insns = get_insns ( ) ;
/* Copy any shared structure that should not be shared. */
unshare_all_rtl ( insns ) ;
1998-08-16 21:35:45 +04:00
# ifdef SETJMP_VIA_SAVE_AREA
/* This must be performed before virutal register instantiation. */
if ( current_function_calls_alloca )
optimize_save_area_alloca ( insns ) ;
# endif
1998-03-29 12:14:27 +04:00
/* Instantiate all virtual registers. */
instantiate_virtual_regs ( current_function_decl , get_insns ( ) ) ;
/* See if we have allocated stack slots that are not directly addressable.
If so , scan all the insns and create explicit address computation
for all references to such slots . */
/* fixup_stack_slots (); */
/* Find all the EH handlers. */
find_exception_handler_labels ( ) ;
/* 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 . */
TIMEVAR ( jump_time , reg_scan ( insns , max_reg_num ( ) , 0 ) ) ;
1998-08-16 21:35:45 +04:00
TIMEVAR ( jump_time , jump_optimize ( insns , ! JUMP_CROSS_JUMP , ! JUMP_NOOP_MOVES ,
JUMP_AFTER_REGSCAN ) ) ;
1998-03-29 12:14:27 +04:00
/* Now is when we stop if -fsyntax-only and -Wreturn-type. */
if ( rtl_dump_and_exit | | flag_syntax_only | | DECL_DEFER_OUTPUT ( decl ) )
goto exit_rest_of_compilation ;
/* Dump rtl code after jump, if we are doing that. */
1998-08-16 21:35:45 +04:00
if ( jump_opt_dump )
dump_rtl ( " .jump " , decl , print_rtl , insns ) ;
1998-03-29 12:14:27 +04:00
/* 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 )
{
1998-08-16 21:35:45 +04:00
if ( cse_dump )
open_dump_file ( " .cse " , decl_printable_name ( decl , 2 ) ) ;
1998-03-29 12:14:27 +04:00
TIMEVAR ( cse_time , reg_scan ( insns , max_reg_num ( ) , 1 ) ) ;
if ( flag_thread_jumps )
/* Hacks by tiemann & kenner. */
TIMEVAR ( jump_time , thread_jumps ( insns , max_reg_num ( ) , 1 ) ) ;
TIMEVAR ( cse_time , tem = cse_main ( insns , max_reg_num ( ) ,
1998-08-16 21:35:45 +04:00
0 , rtl_dump_file ) ) ;
TIMEVAR ( cse_time , delete_trivially_dead_insns ( insns , max_reg_num ( ) ) ) ;
1998-03-29 12:14:27 +04:00
if ( tem | | optimize > 1 )
1998-08-16 21:35:45 +04:00
TIMEVAR ( jump_time , jump_optimize ( insns , ! JUMP_CROSS_JUMP ,
! JUMP_NOOP_MOVES ,
! JUMP_AFTER_REGSCAN ) ) ;
/* Dump rtl code after cse, if we are doing that. */
if ( cse_dump )
close_dump_file ( print_rtl , insns ) ;
1998-03-29 12:14:27 +04:00
}
1998-08-16 21:35:45 +04:00
purge_addressof ( insns ) ;
reg_scan ( insns , max_reg_num ( ) , 1 ) ;
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
if ( addressof_dump )
dump_rtl ( " .addressof " , decl , print_rtl , insns ) ;
/* Perform global cse. */
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
if ( optimize > 0 & & flag_gcse )
{
if ( gcse_dump )
open_dump_file ( " .gcse " , IDENTIFIER_POINTER ( DECL_NAME ( decl ) ) ) ;
TIMEVAR ( gcse_time , gcse_main ( insns , rtl_dump_file ) ) ;
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
if ( gcse_dump )
close_dump_file ( print_rtl , insns ) ;
}
1998-03-29 12:14:27 +04:00
/* Move constant computations out of loops. */
if ( optimize > 0 )
{
1998-08-16 21:35:45 +04:00
if ( loop_dump )
open_dump_file ( " .loop " , decl_printable_name ( decl , 2 ) ) ;
TIMEVAR
( loop_time ,
{
if ( flag_rerun_loop_opt )
1998-03-29 12:14:27 +04:00
{
1998-08-16 21:35:45 +04:00
/* We only want to perform unrolling once. */
loop_optimize ( insns , rtl_dump_file , 0 ) ;
/* 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 ( ) ) ;
/* The regscan pass is currently necessary as the alias
analysis code depends on this information . */
reg_scan ( insns , max_reg_num ( ) , 1 ) ;
}
loop_optimize ( insns , rtl_dump_file , flag_unroll_loops ) ;
} ) ;
/* Dump rtl code after loop opt, if we are doing that. */
if ( loop_dump )
close_dump_file ( print_rtl , insns ) ;
1998-03-29 12:14:27 +04:00
}
1998-08-16 21:35:45 +04:00
if ( optimize > 0 )
1998-03-29 12:14:27 +04:00
{
1998-08-16 21:35:45 +04:00
if ( cse2_dump )
open_dump_file ( " .cse2 " , decl_printable_name ( decl , 2 ) ) ;
if ( flag_rerun_cse_after_loop )
{
/* 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 ( jump_time , reg_scan ( insns , max_reg_num ( ) , 0 ) ) ;
TIMEVAR ( jump_time , jump_optimize ( insns , ! JUMP_CROSS_JUMP ,
! JUMP_NOOP_MOVES ,
JUMP_AFTER_REGSCAN ) ) ;
TIMEVAR ( cse2_time , reg_scan ( insns , max_reg_num ( ) , 0 ) ) ;
TIMEVAR ( cse2_time , tem = cse_main ( insns , max_reg_num ( ) ,
1 , rtl_dump_file ) ) ;
if ( tem )
TIMEVAR ( jump_time , jump_optimize ( insns , ! JUMP_CROSS_JUMP ,
! JUMP_NOOP_MOVES ,
! JUMP_AFTER_REGSCAN ) ) ;
}
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
if ( flag_thread_jumps )
{
/* This pass of jump threading straightens out code
that was kinked by loop optimization . */
TIMEVAR ( jump_time , reg_scan ( insns , max_reg_num ( ) , 0 ) ) ;
TIMEVAR ( jump_time , thread_jumps ( insns , max_reg_num ( ) , 0 ) ) ;
}
/* Dump rtl code after cse, if we are doing that. */
if ( cse2_dump )
close_dump_file ( print_rtl , insns ) ;
}
1998-03-29 12:14:27 +04:00
if ( profile_arc_flag | | flag_test_coverage | | flag_branch_probabilities )
1998-08-16 21:35:45 +04:00
{
if ( branch_prob_dump )
open_dump_file ( " .bp " , decl_printable_name ( decl , 2 ) ) ;
TIMEVAR
( branch_prob_time ,
{
branch_prob ( insns , rtl_dump_file ) ;
} ) ;
if ( branch_prob_dump )
close_dump_file ( print_rtl , insns ) ;
}
1998-03-29 12:14:27 +04:00
/* We are no longer anticipating cse in this function, at least. */
cse_not_expected = 1 ;
/* Now we choose between stupid (pcc-like) register allocation
( if we got the - noreg switch and not - opt )
and smart register allocation . */
if ( optimize > 0 ) /* Stupid allocation probably won't work */
obey_regdecls = 0 ; /* if optimizations being done. */
regclass_init ( ) ;
/* Print function header into flow dump now
because doing the flow analysis makes some of the dump . */
if ( flow_dump )
1998-08-16 21:35:45 +04:00
open_dump_file ( " .flow " , decl_printable_name ( decl , 2 ) ) ;
1998-03-29 12:14:27 +04:00
if ( obey_regdecls )
{
TIMEVAR ( flow_time ,
{
regclass ( insns , max_reg_num ( ) ) ;
stupid_life_analysis ( insns , max_reg_num ( ) ,
1998-08-16 21:35:45 +04:00
rtl_dump_file ) ;
1998-03-29 12:14:27 +04:00
} ) ;
}
else
{
/* Do control and data flow analysis,
and write some of the results to dump file . */
1998-08-16 21:35:45 +04:00
TIMEVAR
( flow_time ,
{
find_basic_blocks ( insns , max_reg_num ( ) , rtl_dump_file , 1 ) ;
life_analysis ( insns , max_reg_num ( ) , rtl_dump_file ) ;
} ) ;
1998-03-29 12:14:27 +04:00
if ( warn_uninitialized )
{
uninitialized_vars_warning ( DECL_INITIAL ( decl ) ) ;
setjmp_args_warning ( ) ;
}
}
/* Dump rtl after flow analysis. */
if ( flow_dump )
1998-08-16 21:35:45 +04:00
close_dump_file ( print_rtl_with_bb , insns ) ;
1998-03-29 12:14:27 +04:00
/* If -opt, try combining insns through substitution. */
if ( optimize > 0 )
1998-08-16 21:35:45 +04:00
{
TIMEVAR ( combine_time , combine_instructions ( insns , max_reg_num ( ) ) ) ;
/* Dump rtl code after insn combination. */
if ( combine_dump )
dump_rtl ( " .combine " , decl , print_rtl_with_bb , insns ) ;
}
1998-03-29 12:14:27 +04:00
/* Register allocation pre-pass, to reduce number of moves
necessary for two - address machines . */
1998-08-16 21:35:45 +04:00
if ( optimize > 0 & & ( flag_regmove | | flag_expensive_optimizations ) )
{
if ( regmove_dump )
open_dump_file ( " .regmove " , decl_printable_name ( decl , 2 ) ) ;
TIMEVAR ( regmove_time , regmove_optimize ( insns , max_reg_num ( ) ,
rtl_dump_file ) ) ;
if ( regmove_dump )
close_dump_file ( print_rtl_with_bb , insns ) ;
}
1998-03-29 12:14:27 +04:00
/* Print function header into sched dump now
because doing the sched analysis makes some of the dump . */
if ( optimize > 0 & & flag_schedule_insns )
{
1998-08-16 21:35:45 +04:00
if ( sched_dump )
open_dump_file ( " .sched " , decl_printable_name ( decl , 2 ) ) ;
1998-03-29 12:14:27 +04:00
/* Do control and data sched analysis,
and write some of the results to dump file . */
1998-08-16 21:35:45 +04:00
TIMEVAR ( sched_time , schedule_insns ( rtl_dump_file ) ) ;
/* Dump rtl after instruction scheduling. */
if ( sched_dump )
close_dump_file ( print_rtl_with_bb , insns ) ;
1998-03-29 12:14:27 +04:00
}
/* Unless we did stupid register allocation,
allocate pseudo - regs that are used only within 1 basic block . */
if ( ! obey_regdecls )
TIMEVAR ( local_alloc_time ,
{
1998-08-16 21:35:45 +04:00
recompute_reg_usage ( insns ) ;
1998-03-29 12:14:27 +04:00
regclass ( insns , max_reg_num ( ) ) ;
local_alloc ( ) ;
} ) ;
/* Dump rtl code after allocating regs within basic blocks. */
if ( local_reg_dump )
1998-08-16 21:35:45 +04:00
{
open_dump_file ( " .lreg " , decl_printable_name ( decl , 2 ) ) ;
TIMEVAR ( dump_time , dump_flow_info ( rtl_dump_file ) ) ;
TIMEVAR ( dump_time , dump_local_alloc ( rtl_dump_file ) ) ;
close_dump_file ( print_rtl_with_bb , insns ) ;
}
1998-03-29 12:14:27 +04:00
if ( global_reg_dump )
1998-08-16 21:35:45 +04:00
open_dump_file ( " .greg " , decl_printable_name ( decl , 2 ) ) ;
1998-03-29 12:14:27 +04:00
/* Save the last label number used so far, so reorg can tell
when it ' s safe to kill spill regs . */
max_label_num_after_reload = max_label_num ( ) ;
/* Unless we did stupid register allocation,
allocate remaining pseudo - regs , then do the reload pass
fixing up any insns that are invalid . */
TIMEVAR ( global_alloc_time ,
{
if ( ! obey_regdecls )
1998-08-16 21:35:45 +04:00
failure = global_alloc ( rtl_dump_file ) ;
1998-03-29 12:14:27 +04:00
else
1998-08-16 21:35:45 +04:00
failure = reload ( insns , 0 , rtl_dump_file ) ;
1998-03-29 12:14:27 +04:00
} ) ;
if ( failure )
goto exit_rest_of_compilation ;
reload_completed = 1 ;
/* Do a very simple CSE pass over just the hard registers. */
if ( optimize > 0 )
reload_cse_regs ( insns ) ;
/* 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 ) ;
1998-08-16 21:35:45 +04:00
if ( global_reg_dump )
{
TIMEVAR ( dump_time , dump_global_regs ( rtl_dump_file ) ) ;
close_dump_file ( print_rtl_with_bb , insns ) ;
}
1998-03-29 12:14:27 +04:00
if ( optimize > 0 & & flag_schedule_insns_after_reload )
{
if ( sched2_dump )
1998-08-16 21:35:45 +04:00
open_dump_file ( " .sched2 " , decl_printable_name ( decl , 2 ) ) ;
1998-03-29 12:14:27 +04:00
/* Do control and data sched analysis again,
and write some more of the results to dump file . */
1998-08-16 21:35:45 +04:00
TIMEVAR ( sched2_time , schedule_insns ( rtl_dump_file ) ) ;
1998-03-29 12:14:27 +04:00
/* Dump rtl after post-reorder instruction scheduling. */
if ( sched2_dump )
1998-08-16 21:35:45 +04:00
close_dump_file ( print_rtl_with_bb , insns ) ;
1998-03-29 12:14:27 +04:00
}
# ifdef LEAF_REGISTERS
leaf_function = 0 ;
if ( optimize > 0 & & only_leaf_regs_used ( ) & & leaf_function_p ( ) )
leaf_function = 1 ;
# endif
/* One more attempt to remove jumps to .+1
left by dead - store - elimination .
Also do cross - jumping this time
and delete no - op move insns . */
if ( optimize > 0 )
{
1998-08-16 21:35:45 +04:00
TIMEVAR ( jump_time , jump_optimize ( insns , JUMP_CROSS_JUMP ,
JUMP_NOOP_MOVES ,
! JUMP_AFTER_REGSCAN ) ) ;
/* Dump rtl code after jump, if we are doing that. */
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
if ( jump2_opt_dump )
dump_rtl ( " .jump2 " , decl , print_rtl_with_bb , insns ) ;
}
1998-03-29 12:14:27 +04:00
/* If a machine dependent reorganization is needed, call it. */
# ifdef MACHINE_DEPENDENT_REORG
MACHINE_DEPENDENT_REORG ( insns ) ;
1998-08-16 21:35:45 +04:00
if ( mach_dep_reorg_dump )
dump_rtl ( " .mach " , decl , print_rtl_with_bb , insns ) ;
1998-03-29 12:14:27 +04:00
# endif
/* If a scheduling pass for delayed branches is to be done,
call the scheduling code . */
# ifdef DELAY_SLOTS
if ( optimize > 0 & & flag_delayed_branch )
{
1998-08-16 21:35:45 +04:00
TIMEVAR ( dbr_sched_time , dbr_schedule ( insns , rtl_dump_file ) ) ;
1998-03-29 12:14:27 +04:00
if ( dbr_sched_dump )
1998-08-16 21:35:45 +04:00
dump_rtl ( " .dbr " , decl , print_rtl_with_bb , insns ) ;
1998-03-29 12:14:27 +04:00
}
# endif
/* Shorten branches. */
TIMEVAR ( shorten_branch_time ,
{
shorten_branches ( get_insns ( ) ) ;
} ) ;
# ifdef STACK_REGS
1998-08-16 21:35:45 +04:00
TIMEVAR ( stack_reg_time , reg_to_stack ( insns , rtl_dump_file ) ) ;
1998-03-29 12:14:27 +04:00
if ( stack_reg_dump )
1998-08-16 21:35:45 +04:00
dump_rtl ( " .stack " , decl , print_rtl_with_bb , insns ) ;
1998-03-29 12:14:27 +04:00
# endif
/* Now turn the rtl into assembler code. */
TIMEVAR ( final_time ,
{
rtx x ;
char * fnname ;
/* Get the function's name, as described by its RTL.
This may be different from the DECL_NAME name used
in the source file . */
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 ) ;
assemble_start_function ( decl , fnname ) ;
final_start_function ( insns , asm_out_file , optimize ) ;
final ( insns , asm_out_file , optimize , 0 ) ;
final_end_function ( insns , asm_out_file , optimize ) ;
assemble_end_function ( decl , fnname ) ;
1998-08-16 21:35:45 +04:00
if ( ! quiet_flag )
fflush ( asm_out_file ) ;
1998-03-29 12:14:27 +04:00
/* Release all memory held by regsets now */
regset_release_memory ( ) ;
} ) ;
/* Write DBX symbols if requested */
/* 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 . */
# ifdef DBX_DEBUGGING_INFO
if ( write_symbols = = DBX_DEBUG )
TIMEVAR ( symout_time , dbxout_function ( decl ) ) ;
# endif
# ifdef DWARF_DEBUGGING_INFO
if ( write_symbols = = DWARF_DEBUG )
TIMEVAR ( symout_time , dwarfout_file_scope_decl ( decl , 0 ) ) ;
# endif
# ifdef DWARF2_DEBUGGING_INFO
if ( write_symbols = = DWARF2_DEBUG )
TIMEVAR ( symout_time , dwarf2out_decl ( decl ) ) ;
# endif
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 ) ;
# endif
/* Put back the tree of subblocks and list of arguments
from before we copied them .
Code generation and the output of debugging info may have modified
the copy , but the original is unchanged . */
if ( saved_block_tree ! = 0 )
{
DECL_INITIAL ( decl ) = saved_block_tree ;
DECL_ARGUMENTS ( decl ) = saved_arguments ;
DECL_ABSTRACT_ORIGIN ( decl ) = NULL_TREE ;
}
reload_completed = 0 ;
1998-08-16 21:35:45 +04:00
TIMEVAR ( final_time ,
{
/* Clear out the insn_length contents now that they are no
longer valid . */
init_insn_lengths ( ) ;
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
/* Clear out the real_constant_chain before some of the rtx's
it runs through become garbage . */
clear_const_double_mem ( ) ;
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
/* Cancel the effect of rtl_in_current_obstack. */
resume_temporary_allocation ( ) ;
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
/* Show no temporary slots allocated. */
init_temp_slots ( ) ;
} ) ;
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04: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 .
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
? ? ? Maybe it isn ' t necessary for expand_start_function to call this
anymore if we do it here ? */
1998-03-29 12:14:27 +04:00
1998-08-16 21:35:45 +04:00
init_recog_no_volatile ( ) ;
1998-03-29 12:14:27 +04:00
/* The parsing time is all the time spent in yyparse
* except * what is spent in this function . */
parse_time - = get_run_time ( ) - start_time ;
}
1998-08-16 21:35:45 +04:00
static void
display_help ( )
{
int undoc ;
long i ;
char * lang ;
# ifndef USE_CPPLIB
printf ( " Usage: %s input [switches] \n " , progname ) ;
printf ( " Switches: \n " ) ;
# endif
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 " ) ;
for ( i = NUM_ELEM ( f_options ) ; i - - ; )
{
char * description = f_options [ i ] . description ;
if ( description ! = NULL & & * description ! = 0 )
printf ( " -f%-21s %s \n " ,
f_options [ i ] . string , description ) ;
}
printf ( " -O[number] Set optimisation level to [number] \n " ) ;
printf ( " -Os Optimise for space rather than speed \n " ) ;
printf ( " -pedantic Issue warnings needed by strict compliance to ANSI C \n " ) ;
printf ( " -pedantic-errors Like -pedantic except that errors are produced \n " ) ;
printf ( " -w Suppress warnings \n " ) ;
printf ( " -W Enable extra warnings \n " ) ;
for ( i = NUM_ELEM ( W_options ) ; i - - ; )
{
char * description = W_options [ i ] . description ;
if ( description ! = NULL & & * description ! = 0 )
printf ( " -W%-21s %s \n " ,
W_options [ i ] . string , description ) ;
}
printf ( " -Wid-clash-<num> Warn if 2 identifiers have the same first <num> chars \n " ) ;
printf ( " -Wlarger-than-<number> Warn if an object is larger than <number> bytes \n " ) ;
printf ( " -p Enable function profiling \n " ) ;
# if defined (BLOCK_PROFILER) || defined (FUNCTION_BLOCK_PROFILER)
printf ( " -a Enable block profiling \n " ) ;
# endif
# if defined (BLOCK_PROFILER) || defined (FUNCTION_BLOCK_PROFILER) || defined FUNCTION_BLOCK_PROFILER_EXIT
printf ( " -ax Enable jump profiling \n " ) ;
# endif
printf ( " -o <file> Place output into <file> \n " ) ;
printf ( " -G <number> Put global and static data smaller than <number> \n " ) ;
printf ( " bytes into a special section (on some targets) \n " ) ;
for ( i = NUM_ELEM ( debug_args ) ; i - - ; )
{
if ( debug_args [ i ] . description ! = NULL )
printf ( " -%-22s %s \n " , debug_args [ i ] . arg , debug_args [ i ] . description ) ;
}
printf ( " -aux-info <file> Emit declaration info into <file>.X \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 HAIFA || defined INSN_SCHEDULING
printf ( " -sched-verbose-<number> Set the verbosity level of the scheduler \n " ) ;
# endif
printf ( " --help Display this information \n " ) ;
undoc = 0 ;
lang = " language " ;
/* 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 , whoes
language specific options are to follow . */
if ( NUM_ELEM ( documented_lang_options ) > 1 )
{
int looking_for_start = 0 ;
printf ( " \n Language specific options: \n " ) ;
for ( i = 0 ; i < NUM_ELEM ( documented_lang_options ) ; i + + )
{
char * description = documented_lang_options [ i ] . description ;
char * option = documented_lang_options [ i ] . option ;
if ( description = = NULL )
undoc = 1 ;
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 ;
printf ( " \n Options for %s: \n " , description ) ;
lang = description ;
}
else
printf ( " %-23.23s %s \n " , option , description ) ;
}
}
if ( undoc )
printf ( " \n There are undocumented %s specific options as well. \n " , lang ) ;
if ( NUM_ELEM ( target_switches ) > 1
# ifdef TARGET_OPTIONS
| | NUM_ELEM ( target_options ) > 1
# endif
)
{
int doc = 0 ;
undoc = 0 ;
printf ( " \n Target specific options: \n " ) ;
for ( i = NUM_ELEM ( target_switches ) ; i - - ; )
{
char * option = target_switches [ i ] . name ;
char * description = target_switches [ i ] . description ;
if ( option = = NULL )
continue ;
else if ( description = = NULL )
undoc = 1 ;
else if ( * description ! = 0 )
doc + = printf ( " %-23.23s %s \n " , option , description ) ;
}
# ifdef TARGET_OPTIONS
for ( i = NUM_ELEM ( target_options ) ; i - - ; )
{
char * option = target_options [ i ] . prefix ;
char * description = target_options [ i ] . description ;
if ( option = = NULL )
continue ;
else if ( description = = NULL )
undoc = 1 ;
else if ( * description ! = 0 )
doc + = printf ( " %-23.23s %s \n " , option , description ) ;
}
# endif
if ( undoc )
if ( doc )
printf ( " \n There are undocumented target specific options as well. \n " ) ;
else
printf ( " They exist, but they are not documented. \n " ) ;
}
}
/* Compare the user specified 'option' with the language
specific ' lang_option ' . Return true if they match , or
if ' option ' is a viable prefix of ' lang_option ' . */
static int
check_lang_option ( option , lang_option )
char * option ;
char * lang_option ;
{
lang_independent_options * indep_options ;
int len ;
long k ;
/* Ignore NULL entries. */
if ( option = = NULL | | lang_option = = NULL )
return 0 ;
len = strlen ( lang_option ) ;
/* If they do not match to the first n characters then fail. */
if ( strncmp ( option , lang_option , len ) ! = 0 )
return 0 ;
/* Do not accept a lang option, if it matches a normal -f or -W
option . Chill defines a - fpack , but we want to support
- fpack - struct . */
/* An exact match is OK */
if ( strlen ( option ) = = len )
return 1 ;
/* If it is not an -f or -W option allow the match */
if ( option [ 0 ] ! = ' - ' )
return 1 ;
switch ( option [ 1 ] )
{
case ' f ' : indep_options = f_options ; break ;
case ' W ' : indep_options = W_options ; break ;
default : return 1 ;
}
/* The option is a -f or -W option.
Skip past the prefix and search for the remainder in the
appropriate table of options . */
option + = 2 ;
if ( option [ 0 ] = = ' n ' & & option [ 1 ] = = ' o ' & & option [ 2 ] = = ' - ' )
option + = 3 ;
for ( k = NUM_ELEM ( indep_options ) ; k - - ; )
{
if ( ! strcmp ( option , indep_options [ k ] . string ) )
{
/* The option matched a language independent option,
do not allow the language specific match . */
return 0 ;
}
}
/* The option matches the start of the langauge specific option
and it is not an exact match for a language independent option . */
return 1 ;
}
1998-03-29 12:14:27 +04:00
/* Entry point of cc1/c++. Decode command args, then call compile_file.
Exit code is 35 if can ' t open files , 34 if fatal error ,
33 if had nonfatal errors , else success . */
int
main ( argc , argv , envp )
int argc ;
char * * argv ;
char * * envp ;
{
register int i ;
char * filename = 0 ;
int flag_print_mem = 0 ;
int version_flag = 0 ;
char * p ;
/* save in case md file wants to emit args as a comment. */
save_argc = argc ;
save_argv = argv ;
p = argv [ 0 ] + strlen ( argv [ 0 ] ) ;
while ( p ! = argv [ 0 ] & & p [ - 1 ] ! = ' / '
# ifdef DIR_SEPARATOR
& & p [ - 1 ] ! = DIR_SEPARATOR
# endif
)
- - p ;
progname = p ;
1998-08-16 21:35:45 +04:00
# if defined (RLIMIT_STACK) && defined (HAVE_GETRLIMIT) && defined (HAVE_SETRLIMIT)
1998-03-29 12:14:27 +04:00
/* Get rid of any avoidable limit on stack size. */
{
struct rlimit rlim ;
/* Set the stack limit huge so that alloca does not fail. */
getrlimit ( RLIMIT_STACK , & rlim ) ;
rlim . rlim_cur = rlim . rlim_max ;
setrlimit ( RLIMIT_STACK , & rlim ) ;
}
1998-08-16 21:35:45 +04:00
# endif
1998-03-29 12:14:27 +04:00
signal ( SIGFPE , float_signal ) ;
# ifdef SIGPIPE
signal ( SIGPIPE , pipe_closed ) ;
# endif
decl_printable_name = decl_name ;
lang_expand_expr = ( struct rtx_def * ( * ) ( ) ) do_abort ;
/* 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
1998-08-16 21:35:45 +04:00
/* Perform language-specific options intialization. */
lang_init_options ( ) ;
1998-03-29 12:14:27 +04: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 ;
}
else if ( argv [ i ] [ 0 ] = = ' - ' & & argv [ i ] [ 1 ] = = ' O ' )
{
1998-08-16 21:35:45 +04:00
/* Handle -Os, -O2, -O3, -O69, ... */
1998-03-29 12:14:27 +04:00
char * p = & argv [ i ] [ 2 ] ;
int c ;
1998-08-16 21:35:45 +04:00
if ( ( p [ 0 ] = = ' s ' ) & & ( p [ 1 ] = = 0 ) )
optimize_size = 1 ;
else
{
while ( ( c = * p + + ) )
if ( ! ( c > = ' 0 ' & & c < = ' 9 ' ) )
break ;
if ( c = = 0 )
optimize = atoi ( & argv [ i ] [ 2 ] ) ;
}
1998-03-29 12:14:27 +04:00
}
}
1998-08-16 21:35:45 +04:00
/* Optimizing for size forces optimize to be no less than 2. */
if ( optimize_size & & ( optimize < 2 ) )
optimize = 2 ;
1998-03-29 12:14:27 +04:00
obey_regdecls = ( optimize = = 0 ) ;
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
}
if ( optimize > = 2 )
{
flag_cse_follow_jumps = 1 ;
flag_cse_skip_blocks = 1 ;
1998-08-16 21:35:45 +04:00
flag_gcse = 1 ;
1998-03-29 12:14:27 +04:00
flag_expensive_optimizations = 1 ;
flag_strength_reduce = 1 ;
flag_rerun_cse_after_loop = 1 ;
flag_rerun_loop_opt = 1 ;
flag_caller_saves = 1 ;
flag_force_mem = 1 ;
# ifdef INSN_SCHEDULING
flag_schedule_insns = 1 ;
flag_schedule_insns_after_reload = 1 ;
# endif
flag_regmove = 1 ;
1998-08-16 21:35:45 +04:00
/* We don't set flag_strict_aliasing here because we're still
testing the functionality . After it has been tested , it
should be turned on here . */
1998-03-29 12:14:27 +04:00
}
if ( optimize > = 3 )
{
flag_inline_functions = 1 ;
}
/* Initialize target_flags before OPTIMIZATION_OPTIONS so the latter can
modify it . */
target_flags = 0 ;
set_target_switch ( " " ) ;
# ifdef OPTIMIZATION_OPTIONS
/* Allow default optimizations to be specified on a per-machine basis. */
1998-08-16 21:35:45 +04:00
OPTIMIZATION_OPTIONS ( optimize , optimize_size ) ;
1998-03-29 12:14:27 +04:00
# endif
/* Initialize register usage now so switches may override. */
init_reg_sets ( ) ;
for ( i = 1 ; i < argc ; i + + )
{
1998-08-16 21:35:45 +04:00
size_t j ;
1998-03-29 12:14:27 +04:00
/* If this is a language-specific option,
decode it in a language - specific way . */
1998-08-16 21:35:45 +04:00
for ( j = NUM_ELEM ( documented_lang_options ) ; j - - ; )
if ( check_lang_option ( argv [ i ] , documented_lang_options [ j ] . option ) )
1998-03-29 12:14:27 +04:00
break ;
1998-08-16 21:35:45 +04:00
if ( j ! = - 1 )
{
/* If the option is valid for *some* language,
treat it as valid even if this language doesn ' t understand it . */
int strings_processed = lang_decode_option ( argc - i , argv + i ) ;
/* BEGIN CYGNUS LOCAL --help/nickc */
if ( ! strcmp ( argv [ i ] , " --help " ) )
{
display_help ( ) ;
exit ( 0 ) ;
}
/* END CYGNUS LOCAL */
if ( strings_processed ! = 0 )
i + = strings_processed - 1 ;
}
1998-03-29 12:14:27 +04:00
else if ( argv [ i ] [ 0 ] = = ' - ' & & argv [ i ] [ 1 ] ! = 0 )
{
register char * str = argv [ i ] + 1 ;
if ( str [ 0 ] = = ' Y ' )
str + + ;
if ( str [ 0 ] = = ' m ' )
set_target_switch ( & str [ 1 ] ) ;
else if ( ! strcmp ( str , " dumpbase " ) )
{
dump_base_name = argv [ + + i ] ;
}
else if ( str [ 0 ] = = ' d ' )
{
register char * p = & str [ 1 ] ;
while ( * p )
switch ( * p + + )
{
case ' a ' :
branch_prob_dump = 1 ;
combine_dump = 1 ;
1998-08-16 21:35:45 +04:00
# ifdef DELAY_SLOTS
1998-03-29 12:14:27 +04:00
dbr_sched_dump = 1 ;
1998-08-16 21:35:45 +04:00
# endif
1998-03-29 12:14:27 +04:00
flow_dump = 1 ;
global_reg_dump = 1 ;
jump_opt_dump = 1 ;
1998-08-16 21:35:45 +04:00
addressof_dump = 1 ;
1998-03-29 12:14:27 +04:00
jump2_opt_dump = 1 ;
local_reg_dump = 1 ;
loop_dump = 1 ;
regmove_dump = 1 ;
rtl_dump = 1 ;
cse_dump = 1 , cse2_dump = 1 ;
1998-08-16 21:35:45 +04:00
gcse_dump = 1 ;
1998-03-29 12:14:27 +04:00
sched_dump = 1 ;
sched2_dump = 1 ;
1998-08-16 21:35:45 +04:00
# ifdef STACK_REGS
1998-03-29 12:14:27 +04:00
stack_reg_dump = 1 ;
1998-08-16 21:35:45 +04:00
# endif
# ifdef MACHINE_DEPENDENT_REORG
mach_dep_reorg_dump = 1 ;
# endif
break ;
case ' A ' :
flag_debug_asm = 1 ;
1998-03-29 12:14:27 +04:00
break ;
case ' b ' :
branch_prob_dump = 1 ;
break ;
case ' c ' :
combine_dump = 1 ;
break ;
1998-08-16 21:35:45 +04:00
# ifdef DELAY_SLOTS
1998-03-29 12:14:27 +04:00
case ' d ' :
dbr_sched_dump = 1 ;
break ;
1998-08-16 21:35:45 +04:00
# endif
1998-03-29 12:14:27 +04:00
case ' f ' :
flow_dump = 1 ;
break ;
1998-08-16 21:35:45 +04:00
case ' F ' :
addressof_dump = 1 ;
break ;
1998-03-29 12:14:27 +04:00
case ' g ' :
global_reg_dump = 1 ;
break ;
1998-08-16 21:35:45 +04:00
case ' G ' :
gcse_dump = 1 ;
break ;
1998-03-29 12:14:27 +04:00
case ' j ' :
jump_opt_dump = 1 ;
break ;
case ' J ' :
jump2_opt_dump = 1 ;
break ;
1998-08-16 21:35:45 +04:00
# ifdef STACK_REGS
case ' k ' :
stack_reg_dump = 1 ;
break ;
# endif
1998-03-29 12:14:27 +04:00
case ' l ' :
local_reg_dump = 1 ;
break ;
case ' L ' :
loop_dump = 1 ;
break ;
case ' m ' :
flag_print_mem = 1 ;
break ;
1998-08-16 21:35:45 +04:00
# ifdef MACHINE_DEPENDENT_REORG
case ' M ' :
mach_dep_reorg_dump = 1 ;
break ;
# endif
1998-03-29 12:14:27 +04:00
case ' p ' :
flag_print_asm_name = 1 ;
break ;
case ' r ' :
rtl_dump = 1 ;
break ;
1998-08-16 21:35:45 +04:00
case ' R ' :
sched2_dump = 1 ;
break ;
1998-03-29 12:14:27 +04:00
case ' s ' :
cse_dump = 1 ;
break ;
1998-08-16 21:35:45 +04:00
case ' S ' :
sched_dump = 1 ;
break ;
1998-03-29 12:14:27 +04:00
case ' t ' :
cse2_dump = 1 ;
break ;
case ' N ' :
regmove_dump = 1 ;
break ;
case ' y ' :
set_yydebug ( 1 ) ;
break ;
case ' x ' :
rtl_dump_and_exit = 1 ;
break ;
1998-08-16 21:35:45 +04:00
default :
warning ( " unrecognised gcc debugging option: %c " , p [ - 1 ] ) ;
1998-03-29 12:14:27 +04:00
break ;
}
}
else if ( str [ 0 ] = = ' f ' )
{
register char * p = & str [ 1 ] ;
int found = 0 ;
/* Some kind of -f option.
P ' s value is the option sans ` - f ' .
Search for it in the table of options . */
for ( j = 0 ;
! found & & j < sizeof ( f_options ) / sizeof ( f_options [ 0 ] ) ;
j + + )
{
if ( ! strcmp ( p , f_options [ j ] . string ) )
{
* f_options [ j ] . variable = f_options [ j ] . on_value ;
/* A goto here would be cleaner,
but breaks the vax pcc . */
found = 1 ;
}
if ( p [ 0 ] = = ' n ' & & p [ 1 ] = = ' o ' & & p [ 2 ] = = ' - '
& & ! strcmp ( p + 3 , f_options [ j ] . string ) )
{
* f_options [ j ] . variable = ! f_options [ j ] . on_value ;
found = 1 ;
}
}
if ( found )
;
# ifdef HAIFA
# ifdef INSN_SCHEDULING
else if ( ! strncmp ( p , " sched-verbose- " , 14 ) )
fix_sched_param ( " verbose " , & p [ 14 ] ) ;
# endif
# endif /* HAIFA */
else if ( ! strncmp ( p , " fixed- " , 6 ) )
fix_register ( & p [ 6 ] , 1 , 1 ) ;
else if ( ! strncmp ( p , " call-used- " , 10 ) )
fix_register ( & p [ 10 ] , 0 , 1 ) ;
else if ( ! strncmp ( p , " call-saved- " , 11 ) )
fix_register ( & p [ 11 ] , 0 , 0 ) ;
else
error ( " Invalid option `%s' " , argv [ i ] ) ;
}
else if ( str [ 0 ] = = ' O ' )
{
register char * p = str + 1 ;
1998-08-16 21:35:45 +04:00
if ( * p = = ' s ' )
1998-03-29 12:14:27 +04:00
p + + ;
1998-08-16 21:35:45 +04:00
else
while ( * p & & * p > = ' 0 ' & & * p < = ' 9 ' )
p + + ;
1998-03-29 12:14:27 +04:00
if ( * p = = ' \0 ' )
;
else
error ( " Invalid option `%s' " , argv [ i ] ) ;
}
else if ( ! strcmp ( str , " pedantic " ) )
pedantic = 1 ;
else if ( ! strcmp ( str , " pedantic-errors " ) )
flag_pedantic_errors = pedantic = 1 ;
else if ( ! strcmp ( str , " quiet " ) )
quiet_flag = 1 ;
else if ( ! strcmp ( str , " version " ) )
version_flag = 1 ;
else if ( ! strcmp ( str , " w " ) )
inhibit_warnings = 1 ;
else if ( ! strcmp ( str , " W " ) )
{
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 ;
}
else if ( str [ 0 ] = = ' W ' )
{
register char * p = & str [ 1 ] ;
int found = 0 ;
/* Some kind of -W option.
P ' s value is the option sans ` - W ' .
Search for it in the table of options . */
for ( j = 0 ;
! found & & j < sizeof ( W_options ) / sizeof ( W_options [ 0 ] ) ;
j + + )
{
if ( ! strcmp ( p , W_options [ j ] . string ) )
{
* W_options [ j ] . variable = W_options [ j ] . on_value ;
/* A goto here would be cleaner,
but breaks the vax pcc . */
found = 1 ;
}
if ( p [ 0 ] = = ' n ' & & p [ 1 ] = = ' o ' & & p [ 2 ] = = ' - '
& & ! strcmp ( p + 3 , W_options [ j ] . string ) )
{
* W_options [ j ] . variable = ! W_options [ j ] . on_value ;
found = 1 ;
}
}
if ( found )
;
else if ( ! strncmp ( p , " id-clash- " , 9 ) )
{
char * endp = p + 9 ;
while ( * endp )
{
if ( * endp > = ' 0 ' & & * endp < = ' 9 ' )
endp + + ;
else
{
error ( " Invalid option `%s' " , argv [ i ] ) ;
goto id_clash_lose ;
}
}
warn_id_clash = 1 ;
id_clash_len = atoi ( str + 10 ) ;
id_clash_lose : ;
}
else if ( ! strncmp ( p , " larger-than- " , 12 ) )
{
char * endp = p + 12 ;
while ( * endp )
{
if ( * endp > = ' 0 ' & & * endp < = ' 9 ' )
endp + + ;
else
{
error ( " Invalid option `%s' " , argv [ i ] ) ;
goto larger_than_lose ;
}
}
warn_larger_than = 1 ;
larger_than_size = atoi ( str + 13 ) ;
larger_than_lose : ;
}
else
error ( " Invalid option `%s' " , argv [ i ] ) ;
}
else if ( ! strcmp ( str , " p " ) )
{
profile_flag = 1 ;
}
else if ( ! strcmp ( str , " a " ) )
{
# if !defined (BLOCK_PROFILER) || !defined (FUNCTION_BLOCK_PROFILER)
warning ( " `-a' option (basic block profile) not supported " ) ;
# else
profile_block_flag = ( profile_block_flag < 2 ) ? 1 : 3 ;
# endif
}
else if ( ! strcmp ( str , " ax " ) )
{
# if !defined (FUNCTION_BLOCK_PROFILER_EXIT) || !defined (BLOCK_PROFILER) || !defined (FUNCTION_BLOCK_PROFILER)
warning ( " `-ax' option (jump profiling) not supported " ) ;
# else
profile_block_flag = ( ! profile_block_flag
| | profile_block_flag = = 2 ) ? 2 : 3 ;
# endif
}
else if ( str [ 0 ] = = ' g ' )
{
unsigned len ;
unsigned level ;
/* 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. */
1998-08-16 21:35:45 +04:00
static char * debug_type_names [ ] =
{
1998-03-29 12:14:27 +04:00
" none " , " stabs " , " coff " , " dwarf-1 " , " dwarf-2 " , " xcoff "
} ;
/* Look up STR in the table. */
for ( da = debug_args ; da - > arg ; da + + )
{
if ( ! strncmp ( str , da - > arg , strlen ( da - > arg ) ) )
{
enum debug_info_type type = da - > debug_type ;
char * p , * q ;
p = str + strlen ( da - > arg ) ;
if ( * p & & ( * p < ' 0 ' | | * p > ' 9 ' ) )
continue ;
len = p - str ;
1998-08-16 21:35:45 +04:00
q = p ;
1998-03-29 12:14:27 +04:00
while ( * q & & ( * q > = ' 0 ' & & * q < = ' 9 ' ) )
q + + ;
if ( * p )
{
level = atoi ( p ) ;
if ( len > 1 & & ! strncmp ( str , " gdwarf " , len ) )
{
error ( " use -gdwarf -g%d for DWARF v1, level %d " ,
level , level ) ;
if ( level = = 2 )
error ( " use -gdwarf-2 for DWARF v2 " ) ;
}
}
else
level = 2 ; /* default debugging info level */
if ( * q | | level > 3 )
{
warning ( " invalid debug level specification in option: `-%s' " ,
str ) ;
/* ??? This error message is incorrect in the case of
- g4 - g . */
warning ( " no debugging information will be generated " ) ;
level = 0 ;
}
if ( type = = NO_DEBUG )
{
type = PREFERRED_DEBUGGING_TYPE ;
if ( len > 1 & & strncmp ( str , " ggdb " , len ) = = 0 )
{
1998-08-16 21:35:45 +04:00
# if defined (DWARF2_DEBUGGING_INFO) && !defined (LINKER_DOES_NOT_WORK_WITH_DWARF2)
1998-03-29 12:14:27 +04:00
type = DWARF2_DEBUG ;
# else
# ifdef DBX_DEBUGGING_INFO
type = DBX_DEBUG ;
# endif
# endif
}
}
if ( type = = NO_DEBUG )
warning ( " `-%s' not supported by this configuration of GCC " ,
str ) ;
/* 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' " ,
str , debug_type_names [ ( int ) selected_debug_type ] ) ;
else
{
/* If the format has already been set, -g/-ggdb
only change the debug level . */
if ( type_explicitly_set_p
& & da - > debug_type = = NO_DEBUG )
; /* don't change debugging type */
else
{
selected_debug_type = type ;
type_explicitly_set_p = da - > debug_type ! = NO_DEBUG ;
}
write_symbols = ( level = = 0
? NO_DEBUG
: selected_debug_type ) ;
use_gnu_debug_info_extensions = da - > use_extensions_p ;
debug_info_level = ( enum debug_info_level ) level ;
}
break ;
}
}
if ( ! da - > arg )
warning ( " `-%s' not supported by this configuration of GCC " ,
str ) ;
}
else if ( ! strcmp ( str , " o " ) )
{
asm_file_name = argv [ + + i ] ;
}
else if ( str [ 0 ] = = ' G ' )
{
g_switch_set = TRUE ;
g_switch_value = atoi ( ( str [ 1 ] ! = ' \0 ' ) ? str + 1 : argv [ + + i ] ) ;
}
else if ( ! strncmp ( str , " aux-info " , 8 ) )
{
flag_gen_aux_info = 1 ;
aux_info_file_name = ( str [ 8 ] ! = ' \0 ' ? str + 8 : argv [ + + i ] ) ;
}
1998-08-16 21:35:45 +04:00
else if ( ! strcmp ( str , " -help " ) )
{
display_help ( ) ;
exit ( 0 ) ;
}
1998-03-29 12:14:27 +04:00
else
error ( " Invalid option `%s' " , argv [ i ] ) ;
}
else if ( argv [ i ] [ 0 ] = = ' + ' )
error ( " Invalid option `%s' " , argv [ i ] ) ;
else
filename = argv [ i ] ;
}
/* Checker uses the frame pointer. */
if ( flag_check_memory_usage )
flag_omit_frame_pointer = 0 ;
if ( optimize = = 0 )
{
/* Inlining does not work if not optimizing,
so force it not to be done . */
flag_no_inline = 1 ;
warn_inline = 0 ;
/* The c_decode_option and lang_decode_option functions set
this to ` 2 ' if - Wall is used , so we can avoid giving out
lots of errors for people who don ' t realize what - Wall does . */
if ( warn_uninitialized = = 1 )
warning ( " -Wuninitialized is not supported without -O " ) ;
}
# ifdef OVERRIDE_OPTIONS
/* Some machines may reject certain combinations of options. */
OVERRIDE_OPTIONS ;
# endif
if ( exceptions_via_longjmp = = 2 )
{
# ifdef DWARF2_UNWIND_INFO
exceptions_via_longjmp = ! DWARF2_UNWIND_INFO ;
# else
exceptions_via_longjmp = 1 ;
# endif
}
if ( profile_block_flag = = 3 )
{
warning ( " `-ax' and `-a' are conflicting options. `-a' ignored. " ) ;
profile_block_flag = 2 ;
}
/* 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 ;
}
/* 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
/* 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 " ) ;
}
compile_file ( filename ) ;
# if !defined(OS2) && !defined(VMS) && (!defined(_WIN32) || defined (__CYGWIN32__))
if ( flag_print_mem )
{
char * lim = ( char * ) sbrk ( 0 ) ;
1998-08-16 21:35:45 +04:00
fprintf ( stderr , " Data size %ld. \n " , ( long ) ( lim - ( char * ) & environ ) ) ;
1998-03-29 12:14:27 +04:00
fflush ( stderr ) ;
1998-08-16 21:35:45 +04:00
# ifndef __MSDOS__
1998-03-29 12:14:27 +04:00
# ifdef USG
system ( " ps -l 1>&2 " ) ;
# else /* not USG */
system ( " ps v " ) ;
# endif /* not USG */
1998-08-16 21:35:45 +04:00
# endif
1998-03-29 12:14:27 +04:00
}
# endif /* ! OS2 && ! VMS && (! _WIN32 || CYGWIN32) */
if ( errorcount )
exit ( FATAL_EXIT_CODE ) ;
if ( sorrycount )
exit ( FATAL_EXIT_CODE ) ;
exit ( SUCCESS_EXIT_CODE ) ;
return 0 ;
}
/* Decode -m switches. */
/* Decode the switch -mNAME. */
void
set_target_switch ( name )
char * name ;
{
1998-08-16 21:35:45 +04:00
register size_t j ;
1998-03-29 12:14:27 +04:00
int valid = 0 ;
for ( j = 0 ; j < sizeof target_switches / sizeof target_switches [ 0 ] ; 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 = 1 ;
}
# ifdef TARGET_OPTIONS
if ( ! valid )
for ( j = 0 ; j < sizeof target_options / sizeof target_options [ 0 ] ; j + + )
{
int len = strlen ( target_options [ j ] . prefix ) ;
if ( ! strncmp ( target_options [ j ] . prefix , name , len ) )
{
* target_options [ j ] . variable = name + len ;
valid = 1 ;
}
}
# endif
if ( ! valid )
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 ) . */
void
print_version ( file , indent )
FILE * file ;
char * indent ;
{
fprintf ( file , " %s%s%s version %s " , indent , * indent ! = 0 ? " " : " " ,
language_string , version_string ) ;
fprintf ( file , " (%s) " , TARGET_NAME ) ;
# ifdef __GNUC__
# ifndef __VERSION__
# define __VERSION__ "[unknown]"
# endif
fprintf ( file , " compiled by GNU C version %s. \n " , __VERSION__ ) ;
# else
fprintf ( file , " compiled by CC. \n " ) ;
# endif
}
/* 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 . */
int
print_single_switch ( file , pos , max , indent , sep , term , type , name )
FILE * file ;
int pos , max ;
char * indent , * sep , * term , * type , * name ;
{
/* 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 ) ;
if ( pos ! = 0
& & pos + len > max )
{
fprintf ( file , " %s " , term ) ;
pos = 0 ;
}
if ( pos = = 0 )
{
fprintf ( file , " %s " , indent ) ;
pos = strlen ( indent ) ;
}
fprintf ( file , " %s%s%s " , sep , type , name ) ;
pos + = len ;
return pos ;
}
/* 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 . */
void
print_switch_values ( file , pos , max , indent , sep , term )
FILE * file ;
int pos , max ;
char * indent , * sep , * term ;
{
1998-08-16 21:35:45 +04:00
size_t j ;
1998-03-29 12:14:27 +04:00
char * * p ;
/* Print the options as passed. */
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 + + ;
continue ;
}
if ( strcmp ( * p , " -quiet " ) = = 0 )
continue ;
if ( strcmp ( * p , " -version " ) = = 0 )
continue ;
if ( ( * p ) [ 1 ] = = ' d ' )
continue ;
pos = print_single_switch ( file , pos , max , indent , sep , term , * p , " " ) ;
}
if ( pos > 0 )
fprintf ( file , " %s " , term ) ;
/* Print the -f and -m options that have been enabled.
We don ' t handle language specific options but printing argv
should suffice . */
pos = print_single_switch ( file , 0 , max , indent , * indent ? " " : " " , term ,
" options enabled: " , " " ) ;
for ( j = 0 ; j < sizeof f_options / sizeof f_options [ 0 ] ; 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 ) ;
/* Print target specific options. */
for ( j = 0 ; j < sizeof target_switches / sizeof target_switches [ 0 ] ; 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 ) ;
}
# ifdef TARGET_OPTIONS
for ( j = 0 ; j < sizeof target_options / sizeof target_options [ 0 ] ; 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
fprintf ( file , " %s " , term ) ;
}
/* Record the beginning of a new source file, named FILENAME. */
void
debug_start_source_file ( filename )
register char * filename ;
{
# ifdef DBX_DEBUGGING_INFO
if ( write_symbols = = DBX_DEBUG )
dbxout_start_new_source_file ( filename ) ;
# endif
# ifdef DWARF_DEBUGGING_INFO
if ( debug_info_level = = DINFO_LEVEL_VERBOSE
& & write_symbols = = DWARF_DEBUG )
dwarfout_start_new_source_file ( filename ) ;
# endif /* DWARF_DEBUGGING_INFO */
# ifdef DWARF2_DEBUGGING_INFO
if ( debug_info_level = = DINFO_LEVEL_VERBOSE
& & write_symbols = = DWARF2_DEBUG )
dwarf2out_start_source_file ( filename ) ;
# endif /* DWARF2_DEBUGGING_INFO */
# ifdef SDB_DEBUGGING_INFO
if ( write_symbols = = SDB_DEBUG )
sdbout_start_new_source_file ( filename ) ;
# endif
}
/* Record the resumption of a source file. LINENO is the line number in
the source file we are returning to . */
void
debug_end_source_file ( lineno )
register unsigned lineno ;
{
# ifdef DBX_DEBUGGING_INFO
if ( write_symbols = = DBX_DEBUG )
dbxout_resume_previous_source_file ( ) ;
# endif
# ifdef DWARF_DEBUGGING_INFO
if ( debug_info_level = = DINFO_LEVEL_VERBOSE
& & write_symbols = = DWARF_DEBUG )
dwarfout_resume_previous_source_file ( lineno ) ;
# endif /* DWARF_DEBUGGING_INFO */
# ifdef DWARF2_DEBUGGING_INFO
if ( debug_info_level = = DINFO_LEVEL_VERBOSE
& & write_symbols = = DWARF2_DEBUG )
dwarf2out_end_source_file ( ) ;
# endif /* DWARF2_DEBUGGING_INFO */
# ifdef SDB_DEBUGGING_INFO
if ( write_symbols = = SDB_DEBUG )
sdbout_resume_previous_source_file ( ) ;
# endif
}
/* Called from check_newline in c-parse.y. The `buffer' parameter contains
the tail part of the directive line , i . e . the part which is past the
initial whitespace , # , whitespace , directive - name , whitespace part . */
void
debug_define ( lineno , buffer )
register unsigned lineno ;
register char * buffer ;
{
# ifdef DWARF_DEBUGGING_INFO
if ( debug_info_level = = DINFO_LEVEL_VERBOSE
& & write_symbols = = DWARF_DEBUG )
dwarfout_define ( lineno , buffer ) ;
# endif /* DWARF_DEBUGGING_INFO */
# ifdef DWARF2_DEBUGGING_INFO
if ( debug_info_level = = DINFO_LEVEL_VERBOSE
& & write_symbols = = DWARF2_DEBUG )
dwarf2out_define ( lineno , buffer ) ;
# endif /* DWARF2_DEBUGGING_INFO */
}
/* Called from check_newline in c-parse.y. The `buffer' parameter contains
the tail part of the directive line , i . e . the part which is past the
initial whitespace , # , whitespace , directive - name , whitespace part . */
void
debug_undef ( lineno , buffer )
register unsigned lineno ;
register char * buffer ;
{
# ifdef DWARF_DEBUGGING_INFO
if ( debug_info_level = = DINFO_LEVEL_VERBOSE
& & write_symbols = = DWARF_DEBUG )
dwarfout_undef ( lineno , buffer ) ;
# endif /* DWARF_DEBUGGING_INFO */
# ifdef DWARF2_DEBUGGING_INFO
if ( debug_info_level = = DINFO_LEVEL_VERBOSE
& & write_symbols = = DWARF2_DEBUG )
dwarf2out_undef ( lineno , buffer ) ;
# endif /* DWARF2_DEBUGGING_INFO */
}