toplev.c revision 52558
118334Speter/* Top level of GNU C compiler 252558Sobrien Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc. 318334Speter 418334SpeterThis file is part of GNU CC. 518334Speter 618334SpeterGNU CC is free software; you can redistribute it and/or modify 718334Speterit under the terms of the GNU General Public License as published by 818334Speterthe Free Software Foundation; either version 2, or (at your option) 918334Speterany later version. 1018334Speter 1118334SpeterGNU CC is distributed in the hope that it will be useful, 1218334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of 1318334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1418334SpeterGNU General Public License for more details. 1518334Speter 1618334SpeterYou should have received a copy of the GNU General Public License 1718334Speteralong with GNU CC; see the file COPYING. If not, write to 1818334Speterthe Free Software Foundation, 59 Temple Place - Suite 330, 1918334SpeterBoston, MA 02111-1307, USA. */ 2018334Speter 2152558Sobrien/* $FreeBSD: head/contrib/gcc/toplev.c 52558 1999-10-27 09:31:52Z obrien $ */ 2252558Sobrien 2318334Speter/* This is the top level of cc1/c++. 2418334Speter It parses command args, opens files, invokes the various passes 2518334Speter in the proper order, and counts the time used by each. 2618334Speter Error messages and low-level interface to malloc also handled here. */ 2718334Speter 2818334Speter#include "config.h" 2950615Sobrien#undef FLOAT /* This is for hpux. They should change hpux. */ 3050615Sobrien#undef FFS /* Some systems define this in param.h. */ 3150615Sobrien#include "system.h" 3218334Speter#include <signal.h> 3318334Speter#include <setjmp.h> 3418334Speter 3550615Sobrien#ifdef HAVE_SYS_RESOURCE_H 3650615Sobrien# include <sys/resource.h> 3718334Speter#endif 3850615Sobrien 3950615Sobrien#ifdef HAVE_SYS_TIMES_H 4050615Sobrien# include <sys/times.h> 4118334Speter#endif 4218334Speter 4318334Speter#include "input.h" 4418334Speter#include "tree.h" 4518334Speter#include "rtl.h" 4618334Speter#include "flags.h" 4718334Speter#include "insn-attr.h" 4850615Sobrien#include "insn-codes.h" 4950615Sobrien#include "insn-config.h" 5050615Sobrien#include "recog.h" 5118334Speter#include "defaults.h" 5218334Speter#include "output.h" 5350615Sobrien#include "except.h" 5450615Sobrien#include "toplev.h" 5552558Sobrien#include "expr.h" 5652558Sobrien#include "basic-block.h" 5752558Sobrien#include "intl.h" 5818334Speter 5950615Sobrien#ifdef DWARF_DEBUGGING_INFO 6050615Sobrien#include "dwarfout.h" 6150615Sobrien#endif 6250615Sobrien 6350615Sobrien#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO) 6450615Sobrien#include "dwarf2out.h" 6550615Sobrien#endif 6650615Sobrien 6750615Sobrien#if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO) 6850615Sobrien#include "dbxout.h" 6950615Sobrien#endif 7050615Sobrien 7150615Sobrien#ifdef SDB_DEBUGGING_INFO 7250615Sobrien#include "sdbout.h" 7350615Sobrien#endif 7450615Sobrien 7518334Speter#ifdef XCOFF_DEBUGGING_INFO 7618334Speter#include "xcoffout.h" 7718334Speter#endif 7818334Speter 7918334Speter#ifdef VMS 8018334Speter/* The extra parameters substantially improve the I/O performance. */ 8118334Speterstatic FILE * 8218334Spetervms_fopen (fname, type) 8318334Speter char * fname; 8418334Speter char * type; 8518334Speter{ 8618334Speter /* The <stdio.h> in the gcc-vms-1.42 distribution prototypes fopen with two 8718334Speter fixed arguments, which matches ANSI's specification but not VAXCRTL's 8818334Speter pre-ANSI implementation. This hack circumvents the mismatch problem. */ 8918334Speter FILE *(*vmslib_fopen)() = (FILE *(*)()) fopen; 9018334Speter 9118334Speter if (*type == 'w') 9218334Speter return (*vmslib_fopen) (fname, type, "mbc=32", 9318334Speter "deq=64", "fop=tef", "shr=nil"); 9418334Speter else 9518334Speter return (*vmslib_fopen) (fname, type, "mbc=32"); 9618334Speter} 9718334Speter#define fopen vms_fopen 9818334Speter#endif /* VMS */ 9918334Speter 10018334Speter#ifndef DEFAULT_GDB_EXTENSIONS 10118334Speter#define DEFAULT_GDB_EXTENSIONS 1 10218334Speter#endif 10318334Speter 10450615Sobrien/* If more than one debugging type is supported, you must define 10550615Sobrien PREFERRED_DEBUGGING_TYPE to choose a format in a system-dependent way. 10650615Sobrien 10750615Sobrien This is one long line cause VAXC can't handle a \-newline. */ 10850615Sobrien#if 1 < (defined (DBX_DEBUGGING_INFO) + defined (SDB_DEBUGGING_INFO) + defined (DWARF_DEBUGGING_INFO) + defined (DWARF2_DEBUGGING_INFO) + defined (XCOFF_DEBUGGING_INFO)) 10950615Sobrien#ifndef PREFERRED_DEBUGGING_TYPE 11050615SobrienYou Lose! You must define PREFERRED_DEBUGGING_TYPE! 11150615Sobrien#endif /* no PREFERRED_DEBUGGING_TYPE */ 11250615Sobrien#else /* Only one debugging format supported. Define PREFERRED_DEBUGGING_TYPE 11350615Sobrien so the following code needn't care. */ 11450615Sobrien#ifdef DBX_DEBUGGING_INFO 11550615Sobrien#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG 11650615Sobrien#endif 11750615Sobrien#ifdef SDB_DEBUGGING_INFO 11850615Sobrien#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG 11950615Sobrien#endif 12050615Sobrien#ifdef DWARF_DEBUGGING_INFO 12150615Sobrien#define PREFERRED_DEBUGGING_TYPE DWARF_DEBUG 12250615Sobrien#endif 12350615Sobrien#ifdef DWARF2_DEBUGGING_INFO 12450615Sobrien#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG 12550615Sobrien#endif 12650615Sobrien#ifdef XCOFF_DEBUGGING_INFO 12750615Sobrien#define PREFERRED_DEBUGGING_TYPE XCOFF_DEBUG 12850615Sobrien#endif 12950615Sobrien#endif /* More than one debugger format enabled. */ 13050615Sobrien 13150615Sobrien/* If still not defined, must have been because no debugging formats 13250615Sobrien are supported. */ 13350615Sobrien#ifndef PREFERRED_DEBUGGING_TYPE 13450615Sobrien#define PREFERRED_DEBUGGING_TYPE NO_DEBUG 13550615Sobrien#endif 13650615Sobrien 13752558Sobrien#ifndef DIR_SEPARATOR 13852558Sobrien#define DIR_SEPARATOR '/' 13952558Sobrien#endif 14052558Sobrien 14118334Speterextern int rtx_equal_function_value_matters; 14218334Speter 14318334Speter#if ! (defined (VMS) || defined (OS2)) 14418334Speterextern char **environ; 14518334Speter#endif 14618334Speterextern char *version_string, *language_string; 14718334Speter 14818334Speter/* Carry information from ASM_DECLARE_OBJECT_NAME 14918334Speter to ASM_FINISH_DECLARE_OBJECT. */ 15018334Speter 15118334Speterextern int size_directive_output; 15218334Speterextern tree last_assemble_variable_decl; 15318334Speter 15450615Sobrienextern char *init_parse PVPROTO((char *)); 15550615Sobrienextern void finish_parse (); 15618334Speterextern void init_decl_processing (); 15718334Speterextern void init_obstacks (); 15818334Speterextern void init_tree_codes (); 15918334Speterextern void init_rtl (); 16018334Speterextern void init_regs (); 16118334Speterextern void init_optabs (); 16218334Speterextern void init_stmt (); 16318334Speterextern void init_reg_sets (); 16418334Speterextern void dump_flow_info (); 16518334Speterextern void dump_sched_info (); 16618334Speterextern void dump_local_alloc (); 16750615Sobrienextern void regset_release_memory (); 16818334Speter 16950615Sobrienextern void print_rtl (); 17050615Sobrienextern void print_rtl_with_bb (); 17150615Sobrien 17218334Spetervoid rest_of_decl_compilation (); 17352558Sobrienvoid error_with_file_and_line PVPROTO((const char *file, 17452558Sobrien int line, const char *s, ...)); 17552558Sobrienvoid error_with_decl PVPROTO((tree decl, const char *s, ...)); 17652558Sobrienvoid error_for_asm PVPROTO((rtx insn, const char *s, ...)); 17752558Sobrienvoid notice PVPROTO((const char *s, ...)); 17852558Sobrienvoid error PVPROTO((const char *s, ...)); 17952558Sobrienvoid fatal PVPROTO((const char *s, ...)); 18052558Sobrienvoid warning_with_file_and_line PVPROTO((const char *file, 18152558Sobrien int line, const char *s, ...)); 18252558Sobrienvoid warning_with_decl PVPROTO((tree decl, const char *s, ...)); 18352558Sobrienvoid warning PVPROTO((const char *s, ...)); 18452558Sobrienvoid pedwarn PVPROTO((const char *s, ...)); 18552558Sobrienvoid pedwarn_with_decl PVPROTO((tree decl, const char *s, ...)); 18652558Sobrienvoid pedwarn_with_file_and_line PVPROTO((const char *file, 18752558Sobrien int line, const char *s, ...)); 18852558Sobrienvoid sorry PVPROTO((const char *s, ...)); 18952558Sobrienstatic void set_target_switch PROTO((const char *)); 19050615Sobrienstatic char *decl_name PROTO((tree, int)); 19152558Sobrienstatic void vmessage PROTO((const char *, const char *, va_list)); 19252558Sobrienstatic void v_message_with_file_and_line PROTO((const char *, int, int, 19352558Sobrien const char *, va_list)); 19452558Sobrienstatic void v_message_with_decl PROTO((tree, int, const char *, va_list)); 19550615Sobrienstatic void file_and_line_for_asm PROTO((rtx, char **, int *)); 19652558Sobrienstatic void v_error_with_file_and_line PROTO((const char *, int, 19752558Sobrien const char *, va_list)); 19852558Sobrienstatic void v_error_with_decl PROTO((tree, const char *, va_list)); 19952558Sobrienstatic void v_error_for_asm PROTO((rtx, const char *, va_list)); 20052558Sobrienstatic void verror PROTO((const char *, va_list)); 20152558Sobrienstatic void vfatal PROTO((const char *, va_list)) ATTRIBUTE_NORETURN; 20252558Sobrienstatic void v_warning_with_file_and_line PROTO ((const char *, int, 20352558Sobrien const char *, va_list)); 20452558Sobrienstatic void v_warning_with_decl PROTO((tree, const char *, va_list)); 20552558Sobrienstatic void v_warning_for_asm PROTO((rtx, const char *, va_list)); 20652558Sobrienstatic void vwarning PROTO((const char *, va_list)); 20752558Sobrienstatic void vpedwarn PROTO((const char *, va_list)); 20852558Sobrienstatic void v_pedwarn_with_decl PROTO((tree, const char *, va_list)); 20952558Sobrienstatic void v_pedwarn_with_file_and_line PROTO((const char *, int, 21052558Sobrien const char *, va_list)); 21152558Sobrienstatic void vsorry PROTO((const char *, va_list)); 21252558Sobrienstatic void float_signal PROTO((int)) ATTRIBUTE_NORETURN; 21352558Sobrienstatic void pipe_closed PROTO((int)) ATTRIBUTE_NORETURN; 21452558Sobrien#ifdef ASM_IDENTIFY_LANGUAGE 21552558Sobrien/* This might or might not be used in ASM_IDENTIFY_LANGUAGE. */ 21652558Sobrienstatic void output_lang_identify PROTO((FILE *)) ATTRIBUTE_UNUSED; 21752558Sobrien#endif 21852558Sobrienstatic void open_dump_file PROTO((const char *, const char *)); 21950615Sobrienstatic void close_dump_file PROTO((void (*) (FILE *, rtx), rtx)); 22052558Sobrienstatic void dump_rtl PROTO((const char *, tree, void (*) (FILE *, rtx), rtx)); 22152558Sobrienstatic void clean_dump_file PROTO((const char *)); 22250615Sobrienstatic void compile_file PROTO((char *)); 22350615Sobrienstatic void display_help PROTO ((void)); 22418334Speter 22552558Sobrienstatic void print_version PROTO((FILE *, const char *)); 22652558Sobrienstatic int print_single_switch PROTO((FILE *, int, int, const char *, 22752558Sobrien const char *, const char *, 22852558Sobrien const char *, const char *)); 22952558Sobrienstatic void print_switch_values PROTO((FILE *, int, int, const char *, 23052558Sobrien const char *, const char *)); 23152558Sobrien 23252558Sobrienvoid print_rtl_graph_with_bb PROTO ((const char *, const char *, rtx)); 23352558Sobrienvoid clean_graph_dump_file PROTO ((const char *, const char *)); 23452558Sobrienvoid finish_graph_dump_file PROTO ((const char *, const char *)); 23550615Sobrien/* Length of line when printing switch values. */ 23650615Sobrien#define MAX_LINE 75 23718334Speter 23818334Speter/* Name of program invoked, sans directories. */ 23918334Speter 24018334Speterchar *progname; 24118334Speter 24218334Speter/* Copy of arguments to main. */ 24318334Speterint save_argc; 24418334Speterchar **save_argv; 24518334Speter 24618334Speter/* Name of current original source file (what was input to cpp). 24718334Speter This comes from each #-command in the actual input. */ 24818334Speter 24918334Speterchar *input_filename; 25018334Speter 25118334Speter/* Name of top-level original source file (what was input to cpp). 25218334Speter This comes from the #-command at the beginning of the actual input. 25318334Speter If there isn't any there, then this is the cc1 input file name. */ 25418334Speter 25518334Speterchar *main_input_filename; 25618334Speter 25718334Speter/* Current line number in real source file. */ 25818334Speter 25918334Speterint lineno; 26018334Speter 26152558Sobrien/* Nonzero if it is unsafe to create any new pseudo registers. */ 26252558Sobrienint no_new_pseudos; 26352558Sobrien 26418334Speter/* Stack of currently pending input files. */ 26518334Speter 26618334Speterstruct file_stack *input_file_stack; 26718334Speter 26818334Speter/* Incremented on each change to input_file_stack. */ 26918334Speterint input_file_stack_tick; 27018334Speter 27118334Speter/* FUNCTION_DECL for function now being parsed or compiled. */ 27218334Speter 27318334Speterextern tree current_function_decl; 27418334Speter 27518334Speter/* Name to use as base of names for dump output files. */ 27618334Speter 27752558Sobrienconst char *dump_base_name; 27818334Speter 27918334Speter/* Bit flags that specify the machine subtype we are compiling for. 28018334Speter Bits are tested using macros TARGET_... defined in the tm.h file 28118334Speter and set by `-m...' switches. Must be defined in rtlanal.c. */ 28218334Speter 28318334Speterextern int target_flags; 28418334Speter 28518334Speter/* Flags saying which kinds of debugging dump have been requested. */ 28618334Speter 28718334Speterint rtl_dump = 0; 28818334Speterint rtl_dump_and_exit = 0; 28918334Speterint jump_opt_dump = 0; 29050615Sobrienint addressof_dump = 0; 29118334Speterint cse_dump = 0; 29250615Sobrienint gcse_dump = 0; 29318334Speterint loop_dump = 0; 29418334Speterint cse2_dump = 0; 29550615Sobrienint branch_prob_dump = 0; 29618334Speterint flow_dump = 0; 29718334Speterint combine_dump = 0; 29850615Sobrienint regmove_dump = 0; 29918334Speterint sched_dump = 0; 30018334Speterint local_reg_dump = 0; 30118334Speterint global_reg_dump = 0; 30252558Sobrienint flow2_dump = 0; 30318334Speterint sched2_dump = 0; 30418334Speterint jump2_opt_dump = 0; 30550615Sobrien#ifdef DELAY_SLOTS 30618334Speterint dbr_sched_dump = 0; 30750615Sobrien#endif 30818334Speterint flag_print_asm_name = 0; 30950615Sobrien#ifdef STACK_REGS 31018334Speterint stack_reg_dump = 0; 31150615Sobrien#endif 31250615Sobrien#ifdef MACHINE_DEPENDENT_REORG 31350615Sobrienint mach_dep_reorg_dump = 0; 31450615Sobrien#endif 31552558Sobrienenum graph_dump_types graph_dump_format; 31618334Speter 31718334Speter/* Name for output file of assembly code, specified with -o. */ 31818334Speter 31918334Speterchar *asm_file_name; 32018334Speter 32118334Speter/* Value of the -G xx switch, and whether it was passed or not. */ 32218334Speterint g_switch_value; 32318334Speterint g_switch_set; 32418334Speter 32518334Speter/* Type(s) of debugging information we are producing (if any). 32618334Speter See flags.h for the definitions of the different possible 32718334Speter types of debugging information. */ 32818334Speterenum debug_info_type write_symbols = NO_DEBUG; 32918334Speter 33018334Speter/* Level of debugging information we are producing. See flags.h 33118334Speter for the definitions of the different possible levels. */ 33218334Speterenum debug_info_level debug_info_level = DINFO_LEVEL_NONE; 33318334Speter 33418334Speter/* Nonzero means use GNU-only extensions in the generated symbolic 33518334Speter debugging information. */ 33618334Speter/* Currently, this only has an effect when write_symbols is set to 33718334Speter DBX_DEBUG, XCOFF_DEBUG, or DWARF_DEBUG. */ 33818334Speterint use_gnu_debug_info_extensions = 0; 33918334Speter 34018334Speter/* Nonzero means do optimizations. -O. 34118334Speter Particular numeric values stand for particular amounts of optimization; 34218334Speter thus, -O2 stores 2 here. However, the optimizations beyond the basic 34318334Speter ones are not controlled directly by this variable. Instead, they are 34418334Speter controlled by individual `flag_...' variables that are defaulted 34518334Speter based on this variable. */ 34618334Speter 34718334Speterint optimize = 0; 34818334Speter 34950615Sobrien/* Nonzero means optimize for size. -Os. 35050615Sobrien The only valid values are zero and non-zero. When optimize_size is 35150615Sobrien non-zero, optimize defaults to 2, but certain individual code 35250615Sobrien bloating optimizations are disabled. */ 35350615Sobrien 35450615Sobrienint optimize_size = 0; 35550615Sobrien 35618334Speter/* Number of error messages and warning messages so far. */ 35718334Speter 35818334Speterint errorcount = 0; 35918334Speterint warningcount = 0; 36018334Speterint sorrycount = 0; 36118334Speter 36250615Sobrien/* Pointer to function to compute the name to use to print a declaration. 36350615Sobrien DECL is the declaration in question. 36450615Sobrien VERBOSITY determines what information will be printed: 36550615Sobrien 0: DECL_NAME, demangled as necessary. 36650615Sobrien 1: and scope information. 36750615Sobrien 2: and any other information that might be interesting, such as function 36850615Sobrien parameter types in C++. */ 36918334Speter 37052558Sobrienchar *(*decl_printable_name) PROTO ((tree, int)); 37118334Speter 37218334Speter/* Pointer to function to compute rtl for a language-specific tree code. */ 37318334Speter 37452558Sobrientypedef rtx (*lang_expand_expr_t) 37552558Sobrien PROTO ((union tree_node *, rtx, enum machine_mode, 37652558Sobrien enum expand_modifier modifier)); 37718334Speter 37852558Sobrienlang_expand_expr_t lang_expand_expr = 0; 37952558Sobrien 38052558Sobrientree (*lang_expand_constant) PROTO((tree)) = 0; 38152558Sobrien 38218334Speter/* Pointer to function to finish handling an incomplete decl at the 38318334Speter end of compilation. */ 38418334Speter 38552558Sobrienvoid (*incomplete_decl_finalize_hook) PROTO((tree)) = 0; 38618334Speter 38718334Speter/* Nonzero if generating code to do profiling. */ 38818334Speter 38918334Speterint profile_flag = 0; 39018334Speter 39118334Speter/* Nonzero if generating code to do profiling on a line-by-line basis. */ 39218334Speter 39318334Speterint profile_block_flag; 39418334Speter 39550615Sobrien/* Nonzero if generating code to profile program flow graph arcs. */ 39650615Sobrien 39750615Sobrienint profile_arc_flag = 0; 39850615Sobrien 39950615Sobrien/* Nonzero if generating info for gcov to calculate line test coverage. */ 40050615Sobrien 40150615Sobrienint flag_test_coverage = 0; 40250615Sobrien 40350615Sobrien/* Nonzero indicates that branch taken probabilities should be calculated. */ 40450615Sobrien 40550615Sobrienint flag_branch_probabilities = 0; 40650615Sobrien 40718334Speter/* Nonzero for -pedantic switch: warn about anything 40818334Speter that standard spec forbids. */ 40918334Speter 41018334Speterint pedantic = 0; 41118334Speter 41218334Speter/* Temporarily suppress certain warnings. 41318334Speter This is set while reading code from a system header file. */ 41418334Speter 41518334Speterint in_system_header = 0; 41618334Speter 41718334Speter/* Nonzero means do stupid register allocation. 41818334Speter Currently, this is 1 if `optimize' is 0. */ 41918334Speter 42018334Speterint obey_regdecls = 0; 42118334Speter 42218334Speter/* Don't print functions as they are compiled and don't print 42318334Speter times taken by the various passes. -quiet. */ 42418334Speter 42518334Speterint quiet_flag = 0; 42618334Speter 42718334Speter/* -f flags. */ 42818334Speter 42918334Speter/* Nonzero means `char' should be signed. */ 43018334Speter 43118334Speterint flag_signed_char; 43218334Speter 43318334Speter/* Nonzero means give an enum type only as many bytes as it needs. */ 43418334Speter 43518334Speterint flag_short_enums; 43618334Speter 43718334Speter/* Nonzero for -fcaller-saves: allocate values in regs that need to 43818334Speter be saved across function calls, if that produces overall better code. 43918334Speter Optional now, so people can test it. */ 44018334Speter 44118334Speter#ifdef DEFAULT_CALLER_SAVES 44218334Speterint flag_caller_saves = 1; 44318334Speter#else 44418334Speterint flag_caller_saves = 0; 44518334Speter#endif 44618334Speter 44718334Speter/* Nonzero if structures and unions should be returned in memory. 44818334Speter 44918334Speter This should only be defined if compatibility with another compiler or 45018334Speter with an ABI is needed, because it results in slower code. */ 45118334Speter 45218334Speter#ifndef DEFAULT_PCC_STRUCT_RETURN 45318334Speter#define DEFAULT_PCC_STRUCT_RETURN 1 45418334Speter#endif 45518334Speter 45618334Speter/* Nonzero for -fpcc-struct-return: return values the same way PCC does. */ 45718334Speter 45818334Speterint flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN; 45918334Speter 46018334Speter/* Nonzero for -fforce-mem: load memory value into a register 46118334Speter before arithmetic on it. This makes better cse but slower compilation. */ 46218334Speter 46318334Speterint flag_force_mem = 0; 46418334Speter 46518334Speter/* Nonzero for -fforce-addr: load memory address into a register before 46618334Speter reference to memory. This makes better cse but slower compilation. */ 46718334Speter 46818334Speterint flag_force_addr = 0; 46918334Speter 47018334Speter/* Nonzero for -fdefer-pop: don't pop args after each function call; 47118334Speter instead save them up to pop many calls' args with one insns. */ 47218334Speter 47318334Speterint flag_defer_pop = 0; 47418334Speter 47518334Speter/* Nonzero for -ffloat-store: don't allocate floats and doubles 47618334Speter in extended-precision registers. */ 47718334Speter 47818334Speterint flag_float_store = 0; 47918334Speter 48018334Speter/* Nonzero for -fcse-follow-jumps: 48118334Speter have cse follow jumps to do a more extensive job. */ 48218334Speter 48318334Speterint flag_cse_follow_jumps; 48418334Speter 48518334Speter/* Nonzero for -fcse-skip-blocks: 48618334Speter have cse follow a branch around a block. */ 48718334Speterint flag_cse_skip_blocks; 48818334Speter 48918334Speter/* Nonzero for -fexpensive-optimizations: 49018334Speter perform miscellaneous relatively-expensive optimizations. */ 49118334Speterint flag_expensive_optimizations; 49218334Speter 49318334Speter/* Nonzero for -fthread-jumps: 49418334Speter have jump optimize output of loop. */ 49518334Speter 49618334Speterint flag_thread_jumps; 49718334Speter 49818334Speter/* Nonzero enables strength-reduction in loop.c. */ 49918334Speter 50018334Speterint flag_strength_reduce = 0; 50118334Speter 50218334Speter/* Nonzero enables loop unrolling in unroll.c. Only loops for which the 50318334Speter number of iterations can be calculated at compile-time (UNROLL_COMPLETELY, 50418334Speter UNROLL_MODULO) or at run-time (preconditioned to be UNROLL_MODULO) are 50518334Speter unrolled. */ 50618334Speter 50718334Speterint flag_unroll_loops; 50818334Speter 50918334Speter/* Nonzero enables loop unrolling in unroll.c. All loops are unrolled. 51018334Speter This is generally not a win. */ 51118334Speter 51218334Speterint flag_unroll_all_loops; 51318334Speter 51450615Sobrien/* Nonzero forces all invariant computations in loops to be moved 51550615Sobrien outside the loop. */ 51650615Sobrien 51750615Sobrienint flag_move_all_movables = 0; 51850615Sobrien 51950615Sobrien/* Nonzero forces all general induction variables in loops to be 52050615Sobrien strength reduced. */ 52150615Sobrien 52250615Sobrienint flag_reduce_all_givs = 0; 52350615Sobrien 52450615Sobrien/* Nonzero to perform full register move optimization passes. This is the 52550615Sobrien default for -O2. */ 52650615Sobrien 52750615Sobrienint flag_regmove = 0; 52850615Sobrien 52918334Speter/* Nonzero for -fwritable-strings: 53018334Speter store string constants in data segment and don't uniquize them. */ 53118334Speter 53218334Speterint flag_writable_strings = 0; 53318334Speter 53418334Speter/* Nonzero means don't put addresses of constant functions in registers. 53518334Speter Used for compiling the Unix kernel, where strange substitutions are 53618334Speter done on the assembly output. */ 53718334Speter 53818334Speterint flag_no_function_cse = 0; 53918334Speter 54018334Speter/* Nonzero for -fomit-frame-pointer: 54118334Speter don't make a frame pointer in simple functions that don't require one. */ 54218334Speter 54318334Speterint flag_omit_frame_pointer = 0; 54418334Speter 54550615Sobrien/* Nonzero means place each function into its own section on those platforms 54650615Sobrien which support arbitrary section names and unlimited numbers of sections. */ 54750615Sobrien 54850615Sobrienint flag_function_sections = 0; 54950615Sobrien 55052558Sobrien/* ... and similar for data. */ 55152558Sobrien 55252558Sobrienint flag_data_sections = 0; 55352558Sobrien 55418334Speter/* Nonzero to inhibit use of define_optimization peephole opts. */ 55518334Speter 55618334Speterint flag_no_peephole = 0; 55718334Speter 55818334Speter/* Nonzero allows GCC to violate some IEEE or ANSI rules regarding math 55918334Speter operations in the interest of optimization. For example it allows 56018334Speter GCC to assume arguments to sqrt are nonnegative numbers, allowing 56150615Sobrien faster code for sqrt to be generated. */ 56218334Speter 56318334Speterint flag_fast_math = 0; 56418334Speter 56552558Sobrien/* Nonzero means the front end generally wants `errno' maintained by math 56652558Sobrien operations, like built-in SQRT, unless overridden by flag_fast_math. */ 56752558Sobrien 56852558Sobrienint flag_errno_math = 1; 56952558Sobrien 57052558Sobrien/* 0 means straightforward implementation of complex divide acceptable. 57152558Sobrien 1 means wide ranges of inputs must work for complex divide. 57252558Sobrien 2 means C9X-like requirements for complex divide (not yet implemented). */ 57352558Sobrien 57452558Sobrienint flag_complex_divide_method = 0; 57552558Sobrien 57618334Speter/* Nonzero means all references through pointers are volatile. */ 57718334Speter 57818334Speterint flag_volatile; 57918334Speter 58052558Sobrien/* Nonzero means treat all global and extern variables as volatile. */ 58118334Speter 58218334Speterint flag_volatile_global; 58318334Speter 58452558Sobrien/* Nonzero means treat all static variables as volatile. */ 58552558Sobrien 58652558Sobrienint flag_volatile_static; 58752558Sobrien 58818334Speter/* Nonzero means just do syntax checking; don't output anything. */ 58918334Speter 59018334Speterint flag_syntax_only = 0; 59118334Speter 59250615Sobrien/* Nonzero means perform global cse. */ 59350615Sobrien 59450615Sobrienstatic int flag_gcse; 59550615Sobrien 59618334Speter/* Nonzero means to rerun cse after loop optimization. This increases 59718334Speter compilation time about 20% and picks up a few more common expressions. */ 59818334Speter 59918334Speterstatic int flag_rerun_cse_after_loop; 60018334Speter 60150615Sobrien/* Nonzero means to run loop optimizations twice. */ 60250615Sobrien 60350615Sobrienint flag_rerun_loop_opt; 60450615Sobrien 60518334Speter/* Nonzero for -finline-functions: ok to inline functions that look like 60618334Speter good inline candidates. */ 60718334Speter 60818334Speterint flag_inline_functions; 60918334Speter 61018334Speter/* Nonzero for -fkeep-inline-functions: even if we make a function 61118334Speter go inline everywhere, keep its definition around for debugging 61218334Speter purposes. */ 61318334Speter 61418334Speterint flag_keep_inline_functions; 61518334Speter 61618334Speter/* Nonzero means that functions will not be inlined. */ 61718334Speter 61818334Speterint flag_no_inline; 61918334Speter 62050615Sobrien/* Nonzero means that we should emit static const variables 62150615Sobrien regardless of whether or not optimization is turned on. */ 62250615Sobrien 62350615Sobrienint flag_keep_static_consts = 1; 62450615Sobrien 62518334Speter/* Nonzero means we should be saving declaration info into a .X file. */ 62618334Speter 62718334Speterint flag_gen_aux_info = 0; 62818334Speter 62918334Speter/* Specified name of aux-info file. */ 63018334Speter 63118334Speterstatic char *aux_info_file_name; 63218334Speter 63318334Speter/* Nonzero means make the text shared if supported. */ 63418334Speter 63518334Speterint flag_shared_data; 63618334Speter 63718334Speter/* Nonzero means schedule into delayed branch slots if supported. */ 63818334Speter 63918334Speterint flag_delayed_branch; 64018334Speter 64118334Speter/* Nonzero if we are compiling pure (sharable) code. 64218334Speter Value is 1 if we are doing reasonable (i.e. simple 64318334Speter offset into offset table) pic. Value is 2 if we can 64418334Speter only perform register offsets. */ 64518334Speter 64618334Speterint flag_pic; 64718334Speter 64850615Sobrien/* Nonzero means generate extra code for exception handling and enable 64950615Sobrien exception handling. */ 65018334Speter 65150615Sobrienint flag_exceptions; 65250615Sobrien 65350615Sobrien/* Nonzero means use the new model for exception handling. Replaces 65450615Sobrien -DNEW_EH_MODEL as a compile option. */ 65550615Sobrien 65650615Sobrienint flag_new_exceptions = 0; 65750615Sobrien 65850615Sobrien/* Nonzero means don't place uninitialized global data in common storage 65950615Sobrien by default. */ 66050615Sobrien 66118334Speterint flag_no_common; 66218334Speter 66318334Speter/* Nonzero means pretend it is OK to examine bits of target floats, 66418334Speter even if that isn't true. The resulting code will have incorrect constants, 66518334Speter but the same series of instructions that the native compiler would make. */ 66618334Speter 66718334Speterint flag_pretend_float; 66818334Speter 66918334Speter/* Nonzero means change certain warnings into errors. 67018334Speter Usually these are warnings about failure to conform to some standard. */ 67118334Speter 67218334Speterint flag_pedantic_errors = 0; 67318334Speter 67418334Speter/* flag_schedule_insns means schedule insns within basic blocks (before 67518334Speter local_alloc). 67618334Speter flag_schedule_insns_after_reload means schedule insns after 67718334Speter global_alloc. */ 67818334Speter 67918334Speterint flag_schedule_insns = 0; 68018334Speterint flag_schedule_insns_after_reload = 0; 68118334Speter 68250615Sobrien#ifdef HAIFA 68350615Sobrien/* The following flags have effect only for scheduling before register 68450615Sobrien allocation: 68550615Sobrien 68650615Sobrien flag_schedule_interblock means schedule insns accross basic blocks. 68750615Sobrien flag_schedule_speculative means allow speculative motion of non-load insns. 68850615Sobrien flag_schedule_speculative_load means allow speculative motion of some 68950615Sobrien load insns. 69050615Sobrien flag_schedule_speculative_load_dangerous allows speculative motion of more 69150615Sobrien load insns. */ 69250615Sobrien 69350615Sobrienint flag_schedule_interblock = 1; 69450615Sobrienint flag_schedule_speculative = 1; 69550615Sobrienint flag_schedule_speculative_load = 0; 69650615Sobrienint flag_schedule_speculative_load_dangerous = 0; 69752558Sobrien#endif /* HAIFA */ 69850615Sobrien 69950615Sobrien/* flag_on_branch_count_reg means try to replace add-1,compare,branch tupple 70050615Sobrien by a cheaper branch, on a count register. */ 70150615Sobrienint flag_branch_on_count_reg; 70250615Sobrien 70318334Speter/* -finhibit-size-directive inhibits output of .size for ELF. 70418334Speter This is used only for compiling crtstuff.c, 70518334Speter and it may be extended to other effects 70618334Speter needed for crtstuff.c on other systems. */ 70718334Speterint flag_inhibit_size_directive = 0; 70818334Speter 70918334Speter/* -fverbose-asm causes extra commentary information to be produced in 71018334Speter the generated assembly code (to make it more readable). This option 71118334Speter is generally only of use to those who actually need to read the 71250615Sobrien generated assembly code (perhaps while debugging the compiler itself). 71350615Sobrien -fno-verbose-asm, the default, causes the extra information 71450615Sobrien to be omitted and is useful when comparing two assembler files. */ 71518334Speter 71618334Speterint flag_verbose_asm = 0; 71718334Speter 71850615Sobrien/* -dA causes debug commentary information to be produced in 71950615Sobrien the generated assembly code (to make it more readable). This option 72050615Sobrien is generally only of use to those who actually need to read the 72150615Sobrien generated assembly code (perhaps while debugging the compiler itself). 72250615Sobrien Currently, this switch is only used by dwarfout.c; however, it is intended 72350615Sobrien to be a catchall for printing debug information in the assembler file. */ 72450615Sobrien 72550615Sobrienint flag_debug_asm = 0; 72650615Sobrien 72718334Speter/* -fgnu-linker specifies use of the GNU linker for initializations. 72818334Speter (Or, more generally, a linker that handles initializations.) 72918334Speter -fno-gnu-linker says that collect2 will be used. */ 73018334Speter#ifdef USE_COLLECT2 73118334Speterint flag_gnu_linker = 0; 73218334Speter#else 73318334Speterint flag_gnu_linker = 1; 73418334Speter#endif 73518334Speter 73618334Speter/* Tag all structures with __attribute__(packed) */ 73718334Speterint flag_pack_struct = 0; 73818334Speter 73938510Sbde/* Nonzero means that -Wformat accepts certain system-dependent formats. */ 74038510Sbdeint flag_format_extensions = 0; 74138510Sbde 74250615Sobrien/* Emit code to check for stack overflow; also may cause large objects 74350615Sobrien to be allocated dynamically. */ 74450615Sobrienint flag_stack_check; 74550615Sobrien 74650615Sobrien/* -fcheck-memory-usage causes extra code to be generated in order to check 74750615Sobrien memory accesses. This is used by a detector of bad memory accesses such 74850615Sobrien as Checker. */ 74950615Sobrienint flag_check_memory_usage = 0; 75050615Sobrien 75150615Sobrien/* -fprefix-function-name causes function name to be prefixed. This 75250615Sobrien can be used with -fcheck-memory-usage to isolate code compiled with 75350615Sobrien -fcheck-memory-usage. */ 75450615Sobrienint flag_prefix_function_name = 0; 75550615Sobrien 75650615Sobrien/* 0 if pointer arguments may alias each other. True in C. 75750615Sobrien 1 if pointer arguments may not alias each other but may alias 75850615Sobrien global variables. 75950615Sobrien 2 if pointer arguments may not alias each other and may not 76050615Sobrien alias global variables. True in Fortran. 76150615Sobrien This defaults to 0 for C. */ 76250615Sobrienint flag_argument_noalias = 0; 76350615Sobrien 76450615Sobrien/* Nonzero if we should do (language-dependent) alias analysis. 76550615Sobrien Typically, this analysis will assume that expressions of certain 76650615Sobrien types do not alias expressions of certain other types. Only used 76750615Sobrien if alias analysis (in general) is enabled. */ 76850615Sobrienint flag_strict_aliasing = 0; 76950615Sobrien 77052558Sobrien/* Instrument functions with calls at entry and exit, for profiling. */ 77152558Sobrienint flag_instrument_function_entry_exit = 0; 77250615Sobrien 77352558Sobrien/* Nonzero means ignore `#ident' directives. 0 means handle them. 77452558Sobrien On SVR4 targets, it also controls whether or not to emit a 77552558Sobrien string identifying the compiler. */ 77650615Sobrien 77752558Sobrienint flag_no_ident = 0; 77852558Sobrien 77950615Sobrien/* Table of supported debugging formats. */ 78050615Sobrienstatic struct 78150615Sobrien{ 78252558Sobrien const char * arg; 78350615Sobrien /* Since PREFERRED_DEBUGGING_TYPE isn't necessarily a 78450615Sobrien constant expression, we use NO_DEBUG in its place. */ 78550615Sobrien enum debug_info_type debug_type; 78650615Sobrien int use_extensions_p; 78752558Sobrien const char * description; 78850615Sobrien} *da, 78950615Sobriendebug_args[] = 79050615Sobrien{ 79150615Sobrien { "g", NO_DEBUG, DEFAULT_GDB_EXTENSIONS, 79250615Sobrien "Generate default debug format output" }, 79350615Sobrien { "ggdb", NO_DEBUG, 1, "Generate default extended debug format output" }, 79450615Sobrien#ifdef DBX_DEBUGGING_INFO 79550615Sobrien { "gstabs", DBX_DEBUG, 0, "Generate STABS format debug output" }, 79650615Sobrien { "gstabs+", DBX_DEBUG, 1, "Generate extended STABS format debug output" }, 79750615Sobrien#endif 79850615Sobrien#ifdef DWARF_DEBUGGING_INFO 79950615Sobrien { "gdwarf", DWARF_DEBUG, 0, "Generate DWARF-1 format debug output"}, 80050615Sobrien { "gdwarf+", DWARF_DEBUG, 1, 80150615Sobrien "Generated extended DWARF-1 format debug output" }, 80250615Sobrien#endif 80350615Sobrien#ifdef DWARF2_DEBUGGING_INFO 80450615Sobrien { "gdwarf-2", DWARF2_DEBUG, 0, "Enable DWARF-2 debug output" }, 80550615Sobrien#endif 80650615Sobrien#ifdef XCOFF_DEBUGGING_INFO 80750615Sobrien { "gxcoff", XCOFF_DEBUG, 0, "Generate XCOFF format debug output" }, 80850615Sobrien { "gxcoff+", XCOFF_DEBUG, 1, "Generate extended XCOFF format debug output" }, 80950615Sobrien#endif 81050615Sobrien#ifdef SDB_DEBUGGING_INFO 81150615Sobrien { "gcoff", SDB_DEBUG, 0, "Generate COFF format debug output" }, 81250615Sobrien#endif 81352558Sobrien { 0, 0, 0, 0 } 81450615Sobrien}; 81550615Sobrien 81650615Sobrientypedef struct 81750615Sobrien{ 81852558Sobrien const char * string; 81950615Sobrien int * variable; 82050615Sobrien int on_value; 82152558Sobrien const char * description; 82250615Sobrien} 82350615Sobrienlang_independent_options; 82450615Sobrien 82552558Sobrien/* Add or remove a leading underscore from user symbols. */ 82652558Sobrienint flag_leading_underscore = -1; 82752558Sobrien 82852558Sobrien/* The user symbol prefix after having resolved same. */ 82952558Sobrienconst char *user_label_prefix; 83052558Sobrien 83152558Sobrien/* A default for same. */ 83252558Sobrien#ifndef USER_LABEL_PREFIX 83352558Sobrien#define USER_LABEL_PREFIX "" 83452558Sobrien#endif 83552558Sobrien 83618334Speter/* Table of language-independent -f options. 83718334Speter STRING is the option name. VARIABLE is the address of the variable. 83818334Speter ON_VALUE is the value to store in VARIABLE 83918334Speter if `-fSTRING' is seen as an option. 84018334Speter (If `-fno-STRING' is seen as an option, the opposite value is stored.) */ 84118334Speter 84250615Sobrienlang_independent_options f_options[] = 84318334Speter{ 84450615Sobrien {"float-store", &flag_float_store, 1, 84550615Sobrien "Do not store floats in registers" }, 84650615Sobrien {"volatile", &flag_volatile, 1, 84750615Sobrien "Consider all mem refs through pointers as volatile"}, 84850615Sobrien {"volatile-global", &flag_volatile_global, 1, 84950615Sobrien "Consider all mem refs to global data to be volatile" }, 85052558Sobrien {"volatile-static", &flag_volatile_static, 1, 85152558Sobrien "Consider all mem refs to static data to be volatile" }, 85250615Sobrien {"defer-pop", &flag_defer_pop, 1, 85350615Sobrien "Defer popping functions args from stack until later" }, 85450615Sobrien {"omit-frame-pointer", &flag_omit_frame_pointer, 1, 85550615Sobrien "When possible do not generate stack frames"}, 85650615Sobrien {"cse-follow-jumps", &flag_cse_follow_jumps, 1, 85750615Sobrien "When running CSE, follow jumps to their targets" }, 85850615Sobrien {"cse-skip-blocks", &flag_cse_skip_blocks, 1, 85950615Sobrien "When running CSE, follow conditional jumps" }, 86050615Sobrien {"expensive-optimizations", &flag_expensive_optimizations, 1, 86150615Sobrien "Perform a number of minor, expensive optimisations" }, 86250615Sobrien {"thread-jumps", &flag_thread_jumps, 1, 86350615Sobrien "Perform jump threading optimisations"}, 86450615Sobrien {"strength-reduce", &flag_strength_reduce, 1, 86550615Sobrien "Perform strength reduction optimisations" }, 86650615Sobrien {"unroll-loops", &flag_unroll_loops, 1, 86752558Sobrien "Perform loop unrolling when iteration count is known" }, 86850615Sobrien {"unroll-all-loops", &flag_unroll_all_loops, 1, 86952558Sobrien "Perform loop unrolling for all loops" }, 87050615Sobrien {"move-all-movables", &flag_move_all_movables, 1, 87150615Sobrien "Force all loop invariant computations out of loops" }, 87250615Sobrien {"reduce-all-givs", &flag_reduce_all_givs, 1, 87350615Sobrien "Strength reduce all loop general induction variables" }, 87450615Sobrien {"writable-strings", &flag_writable_strings, 1, 87550615Sobrien "Store strings in writable data section" }, 87650615Sobrien {"peephole", &flag_no_peephole, 0, 87750615Sobrien "Enable machine specific peephole optimisations" }, 87850615Sobrien {"force-mem", &flag_force_mem, 1, 87950615Sobrien "Copy memory operands into registers before using" }, 88050615Sobrien {"force-addr", &flag_force_addr, 1, 88150615Sobrien "Copy memory address constants into regs before using" }, 88250615Sobrien {"function-cse", &flag_no_function_cse, 0, 88350615Sobrien "Allow function addresses to be held in registers" }, 88450615Sobrien {"inline-functions", &flag_inline_functions, 1, 88550615Sobrien "Integrate simple functions into their callers" }, 88650615Sobrien {"keep-inline-functions", &flag_keep_inline_functions, 1, 88750615Sobrien "Generate code for funcs even if they are fully inlined" }, 88850615Sobrien {"inline", &flag_no_inline, 0, 88950615Sobrien "Pay attention to the 'inline' keyword"}, 89050615Sobrien {"keep-static-consts", &flag_keep_static_consts, 1, 89150615Sobrien "Emit static const variables even if they are not used" }, 89250615Sobrien {"syntax-only", &flag_syntax_only, 1, 89350615Sobrien "Check for syntax errors, then stop" }, 89450615Sobrien {"shared-data", &flag_shared_data, 1, 89550615Sobrien "Mark data as shared rather than private" }, 89650615Sobrien {"caller-saves", &flag_caller_saves, 1, 89750615Sobrien "Enable saving registers around function calls" }, 89850615Sobrien {"pcc-struct-return", &flag_pcc_struct_return, 1, 89950615Sobrien "Return 'short' aggregates in memory, not registers" }, 90050615Sobrien {"reg-struct-return", &flag_pcc_struct_return, 0, 90150615Sobrien "Return 'short' aggregates in registers" }, 90250615Sobrien {"delayed-branch", &flag_delayed_branch, 1, 90350615Sobrien "Attempt to fill delay slots of branch instructions" }, 90450615Sobrien {"gcse", &flag_gcse, 1, 90550615Sobrien "Perform the global common subexpression elimination" }, 90650615Sobrien {"rerun-cse-after-loop", &flag_rerun_cse_after_loop, 1, 90750615Sobrien "Run CSE pass after loop optimisations"}, 90850615Sobrien {"rerun-loop-opt", &flag_rerun_loop_opt, 1, 90950615Sobrien "Run the loop optimiser twice"}, 91050615Sobrien {"pretend-float", &flag_pretend_float, 1, 91150615Sobrien "Pretend that host and target use the same FP format"}, 91250615Sobrien {"schedule-insns", &flag_schedule_insns, 1, 91350615Sobrien "Reschedule instructions to avoid pipeline stalls"}, 91450615Sobrien {"schedule-insns2", &flag_schedule_insns_after_reload, 1, 91550615Sobrien "Run two passes of the instruction scheduler"}, 91650615Sobrien#ifdef HAIFA 91750615Sobrien {"sched-interblock",&flag_schedule_interblock, 1, 91850615Sobrien "Enable scheduling across basic blocks" }, 91950615Sobrien {"sched-spec",&flag_schedule_speculative, 1, 92050615Sobrien "Allow speculative motion of non-loads" }, 92150615Sobrien {"sched-spec-load",&flag_schedule_speculative_load, 1, 92250615Sobrien "Allow speculative motion of some loads" }, 92350615Sobrien {"sched-spec-load-dangerous",&flag_schedule_speculative_load_dangerous, 1, 92450615Sobrien "Allow speculative motion of more loads" }, 92552558Sobrien#endif /* HAIFA */ 92650615Sobrien {"branch-count-reg",&flag_branch_on_count_reg, 1, 92750615Sobrien "Replace add,compare,branch with branch on count reg"}, 92850615Sobrien {"pic", &flag_pic, 1, 92950615Sobrien "Generate position independent code, if possible"}, 93050615Sobrien {"PIC", &flag_pic, 2, ""}, 93150615Sobrien {"exceptions", &flag_exceptions, 1, 93250615Sobrien "Enable exception handling" }, 93350615Sobrien {"new-exceptions", &flag_new_exceptions, 1, 93450615Sobrien "Use the new model for exception handling" }, 93550615Sobrien {"sjlj-exceptions", &exceptions_via_longjmp, 1, 93650615Sobrien "Use setjmp/longjmp to handle exceptions" }, 93750615Sobrien {"asynchronous-exceptions", &asynchronous_exceptions, 1, 93850615Sobrien "Support asynchronous exceptions" }, 93950615Sobrien {"profile-arcs", &profile_arc_flag, 1, 94050615Sobrien "Insert arc based program profiling code" }, 94150615Sobrien {"test-coverage", &flag_test_coverage, 1, 94250615Sobrien "Create data files needed by gcov" }, 94350615Sobrien {"branch-probabilities", &flag_branch_probabilities, 1, 94452558Sobrien "Use profiling information for branch probabilities" }, 94550615Sobrien {"fast-math", &flag_fast_math, 1, 94650615Sobrien "Improve FP speed by violating ANSI & IEEE rules" }, 94750615Sobrien {"common", &flag_no_common, 0, 94850615Sobrien "Do not put unitialised globals in the common section" }, 94950615Sobrien {"inhibit-size-directive", &flag_inhibit_size_directive, 1, 95050615Sobrien "Do not generate .size directives" }, 95150615Sobrien {"function-sections", &flag_function_sections, 1, 95250615Sobrien "place each function into its own section" }, 95352558Sobrien {"data-sections", &flag_data_sections, 1, 95452558Sobrien "place data items into their own section" }, 95550615Sobrien {"verbose-asm", &flag_verbose_asm, 1, 95650615Sobrien "Add extra commentry to assembler output"}, 95750615Sobrien {"gnu-linker", &flag_gnu_linker, 1, 95850615Sobrien "Output GNU ld formatted global initialisers"}, 95950615Sobrien {"regmove", &flag_regmove, 1, 96052558Sobrien "Enables a register move optimisation"}, 96152558Sobrien {"optimize-register-move", &flag_regmove, 1, 96252558Sobrien "Do the full regmove optimization pass"}, 96350615Sobrien {"pack-struct", &flag_pack_struct, 1, 96450615Sobrien "Pack structure members together without holes" }, 96550615Sobrien {"format-extensions", &flag_format_extensions, 1, 96650615Sobrien "-Wformat accepts certain FreeBSD system-dependent formats" }, 96750615Sobrien {"stack-check", &flag_stack_check, 1, 96850615Sobrien "Insert stack checking code into the program" }, 96950615Sobrien {"argument-alias", &flag_argument_noalias, 0, 97050615Sobrien "Specify that arguments may alias each other & globals"}, 97150615Sobrien {"argument-noalias", &flag_argument_noalias, 1, 97250615Sobrien "Assume arguments may alias globals but not each other"}, 97350615Sobrien {"argument-noalias-global", &flag_argument_noalias, 2, 97450615Sobrien "Assume arguments do not alias each other or globals" }, 97550615Sobrien {"strict-aliasing", &flag_strict_aliasing, 1, 97650615Sobrien "Assume strict aliasing rules apply" }, 97750615Sobrien {"check-memory-usage", &flag_check_memory_usage, 1, 97850615Sobrien "Generate code to check every memory access" }, 97950615Sobrien {"prefix-function-name", &flag_prefix_function_name, 1, 98050615Sobrien "Add a prefix to all function names" }, 98152558Sobrien {"dump-unnumbered", &flag_dump_unnumbered, 1, 98252558Sobrien "Suppress output of instruction numbers and line number notes in debugging dumps"}, 98352558Sobrien {"instrument-functions", &flag_instrument_function_entry_exit, 1, 98452558Sobrien "Instrument function entry/exit with profiling calls"}, 98552558Sobrien {"leading-underscore", &flag_leading_underscore, 1, 98652558Sobrien "External symbols have a leading underscore" }, 98752558Sobrien {"ident", &flag_no_ident, 0, 98852558Sobrien "Process #ident directives"} 98918334Speter}; 99018334Speter 99150615Sobrien#define NUM_ELEM(a) (sizeof (a) / sizeof ((a)[0])) 99250615Sobrien 99318334Speter/* Table of language-specific options. */ 99418334Speter 99550615Sobrienstatic struct lang_opt 99618334Speter{ 99752558Sobrien const char * option; 99852558Sobrien const char * description; 99950615Sobrien} 100050615Sobriendocumented_lang_options[] = 100150615Sobrien{ 100250615Sobrien /* In order not to overload the --help output, the convention 100350615Sobrien used here is to only describe those options which are not 100450615Sobrien enabled by default. */ 100518334Speter 100650615Sobrien { "-ansi", "Compile just for ANSI C" }, 100750615Sobrien { "-fallow-single-precision", 100850615Sobrien "Do not promote floats to double if using -traditional" }, 100952558Sobrien { "-std= ", "Determine language standard"}, 101018334Speter 101150615Sobrien { "-fsigned-bitfields", "" }, 101250615Sobrien { "-funsigned-bitfields","Make bitfields by unsigned by default" }, 101350615Sobrien { "-fno-signed-bitfields", "" }, 101450615Sobrien { "-fno-unsigned-bitfields","" }, 101550615Sobrien { "-fsigned-char", "Make 'char' be signed by default"}, 101650615Sobrien { "-funsigned-char", "Make 'char' be unsigned by default"}, 101750615Sobrien { "-fno-signed-char", "" }, 101850615Sobrien { "-fno-unsigned-char", "" }, 101918334Speter 102050615Sobrien { "-ftraditional", "" }, 102150615Sobrien { "-traditional", "Attempt to support traditional K&R style C"}, 102250615Sobrien { "-fnotraditional", "" }, 102350615Sobrien { "-fno-traditional", "" }, 102418334Speter 102550615Sobrien { "-fasm", "" }, 102650615Sobrien { "-fno-asm", "Do not recognise the 'asm' keyword" }, 102750615Sobrien { "-fbuiltin", "" }, 102850615Sobrien { "-fno-builtin", "Do not recognise any built in functions" }, 102950615Sobrien { "-fhosted", "Assume normal C execution environment" }, 103050615Sobrien { "-fno-hosted", "" }, 103150615Sobrien { "-ffreestanding", 103250615Sobrien "Assume that standard libraries & main might not exist" }, 103350615Sobrien { "-fno-freestanding", "" }, 103450615Sobrien { "-fcond-mismatch", "Allow different types as args of ? operator"}, 103550615Sobrien { "-fno-cond-mismatch", "" }, 103652558Sobrien { "-fdollars-in-identifiers", "Allow the use of $ inside identifiers" }, 103750615Sobrien { "-fno-dollars-in-identifiers", "" }, 103850615Sobrien { "-fshort-double", "Use the same size for double as for float" }, 103950615Sobrien { "-fno-short-double", "" }, 104050615Sobrien { "-fshort-enums", "Use the smallest fitting integer to hold enums"}, 104150615Sobrien { "-fno-short-enums", "" }, 104218334Speter 104350615Sobrien { "-Wall", "Enable most warning messages" }, 104450615Sobrien { "-Wbad-function-cast", 104550615Sobrien "Warn about casting functions to incompatible types" }, 104650615Sobrien { "-Wno-bad-function-cast", "" }, 104752558Sobrien { "-Wmissing-noreturn", 104852558Sobrien "Warn about functions which might be candidates for attribute noreturn" }, 104952558Sobrien { "-Wno-missing-noreturn", "" }, 105050615Sobrien { "-Wcast-qual", "Warn about casts which discard qualifiers"}, 105150615Sobrien { "-Wno-cast-qual", "" }, 105252558Sobrien { "-Wchar-subscripts", "Warn about subscripts whose type is 'char'"}, 105350615Sobrien { "-Wno-char-subscripts", "" }, 105450615Sobrien { "-Wcomment", "Warn if nested comments are detected" }, 105552558Sobrien { "-Wno-comment", "" }, 105652558Sobrien { "-Wcomments", "Warn if nested comments are detected" }, 105752558Sobrien { "-Wno-comments", "" }, 105850615Sobrien { "-Wconversion", "Warn about possibly confusing type conversions" }, 105950615Sobrien { "-Wno-conversion", "" }, 106050615Sobrien { "-Wformat", "Warn about printf format anomalies" }, 106150615Sobrien { "-Wno-format", "" }, 106250615Sobrien { "-Wimplicit-function-declaration", 106350615Sobrien "Warn about implicit function declarations" }, 106450615Sobrien { "-Wno-implicit-function-declaration", "" }, 106550615Sobrien { "-Werror-implicit-function-declaration", "" }, 106650615Sobrien { "-Wimplicit-int", "Warn when a declaration does not specify a type" }, 106750615Sobrien { "-Wno-implicit-int", "" }, 106850615Sobrien { "-Wimplicit", "" }, 106950615Sobrien { "-Wno-implicit", "" }, 107050615Sobrien { "-Wimport", "Warn about the use of the #import directive" }, 107150615Sobrien { "-Wno-import", "" }, 107250615Sobrien { "-Wlong-long","" }, 107350615Sobrien { "-Wno-long-long", "Do not warn about using 'long long' when -pedantic" }, 107450615Sobrien { "-Wmain", "Warn about suspicious declarations of main" }, 107550615Sobrien { "-Wno-main", "" }, 107650615Sobrien { "-Wmissing-braces", 107750615Sobrien "Warn about possibly missing braces around initialisers" }, 107850615Sobrien { "-Wno-missing-braces", "" }, 107950615Sobrien { "-Wmissing-declarations", 108050615Sobrien "Warn about global funcs without previous declarations"}, 108150615Sobrien { "-Wno-missing-declarations", "" }, 108250615Sobrien { "-Wmissing-prototypes", "Warn about global funcs without prototypes" }, 108350615Sobrien { "-Wno-missing-prototypes", "" }, 108450615Sobrien { "-Wmultichar", "Warn about use of multicharacter literals"}, 108550615Sobrien { "-Wno-multichar", "" }, 108650615Sobrien { "-Wnested-externs", "Warn about externs not at file scope level" }, 108750615Sobrien { "-Wno-nested-externs", "" }, 108850615Sobrien { "-Wparentheses", "Warn about possible missing parentheses" }, 108950615Sobrien { "-Wno-parentheses", "" }, 109050615Sobrien { "-Wpointer-arith", "Warn about function pointer arithmetic" }, 109150615Sobrien { "-Wno-pointer-arith", "" }, 109250615Sobrien { "-Wredundant-decls", 109350615Sobrien "Warn about multiple declarations of the same object" }, 109450615Sobrien { "-Wno-redundant-decls", "" }, 109550615Sobrien { "-Wsign-compare", "Warn about signed/unsigned comparisons" }, 109650615Sobrien { "-Wno-sign-compare", "" }, 109750615Sobrien { "-Wunknown-pragmas", "Warn about unrecognised pragmas" }, 109850615Sobrien { "-Wno-unknown-pragmas", "" }, 109950615Sobrien { "-Wstrict-prototypes", "Warn about non-prototyped function decls" }, 110050615Sobrien { "-Wno-strict-prototypes", "" }, 110152558Sobrien { "-Wtraditional", "Warn about constructs whose meaning change in ANSI C"}, 110250615Sobrien { "-Wno-traditional", "" }, 110350615Sobrien { "-Wtrigraphs", "Warn when trigraphs are encountered" }, 110450615Sobrien { "-Wno-trigraphs", "" }, 110550615Sobrien { "-Wundef", "" }, 110650615Sobrien { "-Wno-undef", "" }, 110750615Sobrien { "-Wwrite-strings", "Mark strings as 'const char *'"}, 110850615Sobrien { "-Wno-write-strings", "" }, 110918334Speter 111050615Sobrien /* These are for languages with USE_CPPLIB. */ 111150615Sobrien /* These options are already documented in cpplib.c */ 111250615Sobrien { "--help", "" }, 111350615Sobrien { "-A", "" }, 111450615Sobrien { "-D", "" }, 111550615Sobrien { "-I", "" }, 111652558Sobrien#if USE_CPPLIB 111752558Sobrien { "-MD", "Print dependencies to FILE.d" }, 111852558Sobrien { "-MMD", "Print dependencies to FILE.d" }, 111952558Sobrien { "-M", "Print dependencies to stdout" }, 112052558Sobrien { "-MM", "Print dependencies to stdout" }, 112152558Sobrien#endif /* USE_CPPLIB */ 112250615Sobrien { "-U", "" }, 112352558Sobrien { "-H", "" }, 112450615Sobrien { "-idirafter", "" }, 112552558Sobrien { "-imacros", "" }, 112652558Sobrien { "-include", "" }, 112750615Sobrien { "-iprefix", "" }, 112850615Sobrien { "-isystem", "" }, 112952558Sobrien { "-iwithprefix", "" }, 113052558Sobrien { "-iwithprefixbefore", "" }, 113150615Sobrien { "-lang-c", "" }, 113250615Sobrien { "-lang-c89", "" }, 113350615Sobrien { "-lang-c++", "" }, 113452558Sobrien { "-remap", "" }, 113550615Sobrien { "-nostdinc", "" }, 113650615Sobrien { "-nostdinc++", "" }, 113750615Sobrien { "-trigraphs", "" }, 113850615Sobrien { "-undef", "" }, 113950615Sobrien 114050615Sobrien#define DEFINE_LANG_NAME(NAME) { NULL, NAME }, 114150615Sobrien 114250615Sobrien /* These are for obj c. */ 114350615Sobrien DEFINE_LANG_NAME ("Objective C") 114450615Sobrien 114550615Sobrien { "-lang-objc", "" }, 114650615Sobrien { "-gen-decls", "Dump decls to a .decl file" }, 114752558Sobrien { "-fgnu-runtime", "Generate code for GNU runtime environment" }, 114850615Sobrien { "-fno-gnu-runtime", "" }, 114950615Sobrien { "-fnext-runtime", "Generate code for NeXT runtime environment" }, 115050615Sobrien { "-fno-next-runtime", "" }, 115150615Sobrien { "-Wselector", "Warn if a selector has multiple methods" }, 115250615Sobrien { "-Wno-selector", "" }, 115350615Sobrien { "-Wprotocol", "" }, 115450615Sobrien { "-Wno-protocol", "Do not warn if inherited methods are unimplemented"}, 115550615Sobrien { "-print-objc-runtime-info", 115650615Sobrien "Generate C header of platform specific features" }, 115750615Sobrien 115818334Speter#include "options.h" 115950615Sobrien 116018334Speter}; 116150615Sobrien 116250615Sobrien/* Here is a table, controlled by the tm.h file, listing each -m switch 116350615Sobrien and which bits in `target_switches' it should set or clear. 116450615Sobrien If VALUE is positive, it is bits to set. 116550615Sobrien If VALUE is negative, -VALUE is bits to clear. 116650615Sobrien (The sign bit is not used so there is no confusion.) */ 116750615Sobrien 116850615Sobrienstruct 116950615Sobrien{ 117052558Sobrien const char * name; 117150615Sobrien int value; 117252558Sobrien const char * description; 117350615Sobrien} 117450615Sobrientarget_switches [] = TARGET_SWITCHES; 117550615Sobrien 117650615Sobrien/* This table is similar, but allows the switch to have a value. */ 117750615Sobrien 117850615Sobrien#ifdef TARGET_OPTIONS 117950615Sobrienstruct 118050615Sobrien{ 118152558Sobrien const char * prefix; 118252558Sobrien const char ** variable; 118352558Sobrien const char * description; 118450615Sobrien} 118550615Sobrientarget_options [] = TARGET_OPTIONS; 118650615Sobrien#endif 118718334Speter 118818334Speter/* Options controlling warnings */ 118918334Speter 119018334Speter/* Don't print warning messages. -w. */ 119118334Speter 119218334Speterint inhibit_warnings = 0; 119318334Speter 119418334Speter/* Print various extra warnings. -W. */ 119518334Speter 119618334Speterint extra_warnings = 0; 119718334Speter 119818334Speter/* Treat warnings as errors. -Werror. */ 119918334Speter 120018334Speterint warnings_are_errors = 0; 120118334Speter 120218334Speter/* Nonzero to warn about unused local variables. */ 120318334Speter 120418334Speterint warn_unused; 120518334Speter 120618334Speter/* Nonzero to warn about variables used before they are initialized. */ 120718334Speter 120818334Speterint warn_uninitialized; 120918334Speter 121018334Speter/* Nonzero means warn about all declarations which shadow others. */ 121118334Speter 121218334Speterint warn_shadow; 121318334Speter 121418334Speter/* Warn if a switch on an enum fails to have a case for every enum value. */ 121518334Speter 121618334Speterint warn_switch; 121718334Speter 121818334Speter/* Nonzero means warn about function definitions that default the return type 121918334Speter or that use a null return and have a return-type other than void. */ 122018334Speter 122118334Speterint warn_return_type; 122218334Speter 122318334Speter/* Nonzero means warn about pointer casts that increase the required 122418334Speter alignment of the target type (and might therefore lead to a crash 122518334Speter due to a misaligned access). */ 122618334Speter 122718334Speterint warn_cast_align; 122818334Speter 122918334Speter/* Nonzero means warn about any identifiers that match in the first N 123018334Speter characters. The value N is in `id_clash_len'. */ 123118334Speter 123218334Speterint warn_id_clash; 123318334Speterunsigned id_clash_len; 123418334Speter 123518334Speter/* Nonzero means warn about any objects definitions whose size is larger 123618334Speter than N bytes. Also want about function definitions whose returned 123718334Speter values are larger than N bytes. The value N is in `larger_than_size'. */ 123818334Speter 123918334Speterint warn_larger_than; 124018334Speterunsigned larger_than_size; 124118334Speter 124218334Speter/* Nonzero means warn if inline function is too large. */ 124318334Speter 124418334Speterint warn_inline; 124518334Speter 124618334Speter/* Warn if a function returns an aggregate, 124718334Speter since there are often incompatible calling conventions for doing this. */ 124818334Speter 124918334Speterint warn_aggregate_return; 125018334Speter 125118334Speter/* Likewise for -W. */ 125218334Speter 125350615Sobrienlang_independent_options W_options[] = 125418334Speter{ 125550615Sobrien {"unused", &warn_unused, 1, "Warn when a variable is unused" }, 125650615Sobrien {"error", &warnings_are_errors, 1, ""}, 125750615Sobrien {"shadow", &warn_shadow, 1, "Warn when one local variable shadows another" }, 125850615Sobrien {"switch", &warn_switch, 1, 125950615Sobrien "Warn about enumerated switches missing a specific case" }, 126050615Sobrien {"aggregate-return", &warn_aggregate_return, 1, 126150615Sobrien "Warn about returning structures, unions or arrays" }, 126250615Sobrien {"cast-align", &warn_cast_align, 1, 126350615Sobrien "Warn about pointer casts which increase alignment" }, 126450615Sobrien {"uninitialized", &warn_uninitialized, 1, 126550615Sobrien "Warn about unitialized automatic variables"}, 126650615Sobrien {"inline", &warn_inline, 1, 126750615Sobrien "Warn when an inlined function cannot be inlined"} 126818334Speter}; 126918334Speter 127018334Speter/* Output files for assembler code (real compiler output) 127118334Speter and debugging dumps. */ 127218334Speter 127318334SpeterFILE *asm_out_file; 127418334SpeterFILE *aux_info_file; 127550615SobrienFILE *rtl_dump_file = NULL; 127618334Speter 127752558Sobrien/* Decode the string P as an integral parameter. 127852558Sobrien If the string is indeed an integer return its numeric value else 127952558Sobrien issue an Invalid Option error for the option PNAME and return DEFVAL. 128052558Sobrien If PNAME is zero just return DEFVAL, do not call error. */ 128152558Sobrien 128252558Sobrienint 128352558Sobrienread_integral_parameter (p, pname, defval) 128452558Sobrien const char *p; 128552558Sobrien const char *pname; 128652558Sobrien const int defval; 128752558Sobrien{ 128852558Sobrien const char *endp = p; 128952558Sobrien 129052558Sobrien while (*endp) 129152558Sobrien { 129252558Sobrien if (*endp >= '0' && *endp <= '9') 129352558Sobrien endp++; 129452558Sobrien else 129552558Sobrien break; 129652558Sobrien } 129752558Sobrien 129852558Sobrien if (*endp != 0) 129952558Sobrien { 130052558Sobrien if (pname != 0) 130152558Sobrien error ("Invalid option `%s'", pname); 130252558Sobrien return defval; 130352558Sobrien } 130452558Sobrien 130552558Sobrien return atoi (p); 130652558Sobrien} 130752558Sobrien 130852558Sobrien 130918334Speter/* Time accumulators, to count the total time spent in various passes. */ 131018334Speter 131118334Speterint parse_time; 131218334Speterint varconst_time; 131318334Speterint integration_time; 131418334Speterint jump_time; 131518334Speterint cse_time; 131650615Sobrienint gcse_time; 131718334Speterint loop_time; 131818334Speterint cse2_time; 131950615Sobrienint branch_prob_time; 132018334Speterint flow_time; 132118334Speterint combine_time; 132250615Sobrienint regmove_time; 132318334Speterint sched_time; 132418334Speterint local_alloc_time; 132518334Speterint global_alloc_time; 132652558Sobrienint flow2_time; 132718334Speterint sched2_time; 132850615Sobrien#ifdef DELAY_SLOTS 132918334Speterint dbr_sched_time; 133050615Sobrien#endif 133118334Speterint shorten_branch_time; 133218334Speterint stack_reg_time; 133318334Speterint final_time; 133418334Speterint symout_time; 133518334Speterint dump_time; 133618334Speter 133718334Speter/* Return time used so far, in microseconds. */ 133818334Speter 133952558Sobrienlong 134018334Speterget_run_time () 134118334Speter{ 134218334Speter if (quiet_flag) 134318334Speter return 0; 134450615Sobrien 134550615Sobrien#ifdef __BEOS__ 134650615Sobrien return 0; 134750615Sobrien#else /* not BeOS */ 134852558Sobrien#if defined (_WIN32) && !defined (__CYGWIN__) 134918334Speter if (clock() < 0) 135018334Speter return 0; 135118334Speter else 135218334Speter return (clock() * 1000); 135318334Speter#else /* not _WIN32 */ 135450615Sobrien#ifdef _SC_CLK_TCK 135550615Sobrien { 135650615Sobrien static int tick; 135750615Sobrien struct tms tms; 135850615Sobrien if (tick == 0) 135950615Sobrien tick = 1000000 / sysconf(_SC_CLK_TCK); 136050615Sobrien times (&tms); 136150615Sobrien return (tms.tms_utime + tms.tms_stime) * tick; 136250615Sobrien } 136350615Sobrien#else 136418334Speter#ifdef USG 136550615Sobrien { 136650615Sobrien struct tms tms; 136750615Sobrien# if HAVE_SYSCONF && defined _SC_CLK_TCK 136850615Sobrien# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */ 136950615Sobrien# else 137050615Sobrien# ifdef CLK_TCK 137150615Sobrien# define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */ 137250615Sobrien# else 137350615Sobrien# define TICKS_PER_SECOND HZ /* traditional UNIX */ 137450615Sobrien# endif 137550615Sobrien# endif 137650615Sobrien times (&tms); 137750615Sobrien return (tms.tms_utime + tms.tms_stime) * (1000000 / TICKS_PER_SECOND); 137850615Sobrien } 137918334Speter#else 138018334Speter#ifndef VMS 138150615Sobrien { 138250615Sobrien struct rusage rusage; 138350615Sobrien getrusage (0, &rusage); 138450615Sobrien return (rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec 138550615Sobrien + rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec); 138650615Sobrien } 138718334Speter#else /* VMS */ 138850615Sobrien { 138950615Sobrien struct 139050615Sobrien { 139150615Sobrien int proc_user_time; 139250615Sobrien int proc_system_time; 139350615Sobrien int child_user_time; 139450615Sobrien int child_system_time; 139550615Sobrien } vms_times; 139650615Sobrien times ((void *) &vms_times); 139750615Sobrien return (vms_times.proc_user_time + vms_times.proc_system_time) * 10000; 139850615Sobrien } 139950615Sobrien#endif /* VMS */ 140050615Sobrien#endif /* USG */ 140150615Sobrien#endif /* _SC_CLK_TCK */ 140250615Sobrien#endif /* _WIN32 */ 140350615Sobrien#endif /* __BEOS__ */ 140418334Speter} 140518334Speter 140618334Speter#define TIMEVAR(VAR, BODY) \ 140718334Speterdo { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0) 140818334Speter 140918334Spetervoid 141018334Speterprint_time (str, total) 141152558Sobrien const char *str; 141218334Speter int total; 141318334Speter{ 141418334Speter fprintf (stderr, 141518334Speter "time in %s: %d.%06d\n", 141618334Speter str, total / 1000000, total % 1000000); 141718334Speter} 141818334Speter 141918334Speter/* Count an error or warning. Return 1 if the message should be printed. */ 142018334Speter 142118334Speterint 142218334Spetercount_error (warningp) 142318334Speter int warningp; 142418334Speter{ 142518334Speter if (warningp && inhibit_warnings) 142618334Speter return 0; 142718334Speter 142818334Speter if (warningp && !warnings_are_errors) 142918334Speter warningcount++; 143018334Speter else 143118334Speter { 143218334Speter static int warning_message = 0; 143318334Speter 143418334Speter if (warningp && !warning_message) 143518334Speter { 143652558Sobrien notice ("%s: warnings being treated as errors\n", progname); 143718334Speter warning_message = 1; 143818334Speter } 143918334Speter errorcount++; 144018334Speter } 144118334Speter 144218334Speter return 1; 144318334Speter} 144418334Speter 144518334Speter/* Print a fatal error message. NAME is the text. 144618334Speter Also include a system error message based on `errno'. */ 144718334Speter 144818334Spetervoid 144918334Speterpfatal_with_name (name) 145052558Sobrien const char *name; 145118334Speter{ 145218334Speter fprintf (stderr, "%s: ", progname); 145318334Speter perror (name); 145418334Speter exit (FATAL_EXIT_CODE); 145518334Speter} 145618334Speter 145718334Spetervoid 145818334Speterfatal_io_error (name) 145952558Sobrien const char *name; 146018334Speter{ 146152558Sobrien notice ("%s: %s: I/O error\n", progname, name); 146218334Speter exit (FATAL_EXIT_CODE); 146318334Speter} 146418334Speter 146518334Speter/* Called to give a better error message for a bad insn rather than 146618334Speter just calling abort(). */ 146718334Speter 146818334Spetervoid 146952558Sobrienfatal_insn VPROTO((const char *msgid, rtx insn, ...)) 147018334Speter{ 147152558Sobrien#ifndef ANSI_PROTOTYPES 147252558Sobrien const char *msgid; 147352558Sobrien rtx insn; 147452558Sobrien#endif 147552558Sobrien va_list ap; 147652558Sobrien 147752558Sobrien VA_START (ap, insn); 147852558Sobrien 147952558Sobrien#ifndef ANSI_PROTOTYPES 148052558Sobrien msgid = va_arg (ap, const char *); 148152558Sobrien insn = va_arg (ap, rtx); 148252558Sobrien#endif 148352558Sobrien 148452558Sobrien verror (msgid, ap); 148550615Sobrien debug_rtx (insn); 148652558Sobrien exit (FATAL_EXIT_CODE); 148718334Speter} 148818334Speter 148918334Speter/* Called to give a better error message when we don't have an insn to match 149018334Speter what we are looking for or if the insn's constraints aren't satisfied, 149118334Speter rather than just calling abort(). */ 149218334Speter 149318334Spetervoid 149418334Speterfatal_insn_not_found (insn) 149518334Speter rtx insn; 149618334Speter{ 149718334Speter if (INSN_CODE (insn) < 0) 149818334Speter fatal_insn ("internal error--unrecognizable insn:", insn); 149918334Speter else 150018334Speter fatal_insn ("internal error--insn does not satisfy its constraints:", insn); 150118334Speter} 150218334Speter 150318334Speter/* This is the default decl_printable_name function. */ 150418334Speter 150518334Speterstatic char * 150650615Sobriendecl_name (decl, verbosity) 150718334Speter tree decl; 150852558Sobrien int verbosity ATTRIBUTE_UNUSED; 150918334Speter{ 151018334Speter return IDENTIFIER_POINTER (DECL_NAME (decl)); 151118334Speter} 151218334Speter 151318334Speterstatic int need_error_newline; 151418334Speter 151518334Speter/* Function of last error message; 151618334Speter more generally, function such that if next error message is in it 151718334Speter then we don't have to mention the function name. */ 151818334Speterstatic tree last_error_function = NULL; 151918334Speter 152018334Speter/* Used to detect when input_file_stack has changed since last described. */ 152118334Speterstatic int last_error_tick; 152218334Speter 152318334Speter/* Called when the start of a function definition is parsed, 152418334Speter this function prints on stderr the name of the function. */ 152518334Speter 152618334Spetervoid 152718334Speterannounce_function (decl) 152818334Speter tree decl; 152918334Speter{ 153018334Speter if (! quiet_flag) 153118334Speter { 153218334Speter if (rtl_dump_and_exit) 153318334Speter fprintf (stderr, "%s ", IDENTIFIER_POINTER (DECL_NAME (decl))); 153418334Speter else 153550615Sobrien fprintf (stderr, " %s", (*decl_printable_name) (decl, 2)); 153618334Speter fflush (stderr); 153718334Speter need_error_newline = 1; 153818334Speter last_error_function = current_function_decl; 153918334Speter } 154018334Speter} 154118334Speter 154218334Speter/* The default function to print out name of current function that caused 154318334Speter an error. */ 154418334Speter 154518334Spetervoid 154618334Speterdefault_print_error_function (file) 154752558Sobrien const char *file; 154818334Speter{ 154918334Speter if (last_error_function != current_function_decl) 155018334Speter { 155118334Speter if (file) 155218334Speter fprintf (stderr, "%s: ", file); 155318334Speter 155418334Speter if (current_function_decl == NULL) 155552558Sobrien notice ("At top level:\n"); 155618334Speter else 155752558Sobrien notice ((TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE 155852558Sobrien ? "In method `%s':\n" 155952558Sobrien : "In function `%s':\n"), 156052558Sobrien (*decl_printable_name) (current_function_decl, 2)); 156118334Speter 156218334Speter last_error_function = current_function_decl; 156318334Speter } 156418334Speter} 156518334Speter 156618334Speter/* Called by report_error_function to print out function name. 156750615Sobrien * Default may be overridden by language front-ends. */ 156818334Speter 156952558Sobrienvoid (*print_error_function) PROTO((const char *)) = 157052558Sobrien default_print_error_function; 157118334Speter 157218334Speter/* Prints out, if necessary, the name of the current function 157352558Sobrien that caused an error. Called from all error and warning functions. 157452558Sobrien We ignore the FILE parameter, as it cannot be relied upon. */ 157518334Speter 157618334Spetervoid 157718334Speterreport_error_function (file) 157852558Sobrien const char *file ATTRIBUTE_UNUSED; 157918334Speter{ 158018334Speter struct file_stack *p; 158118334Speter 158218334Speter if (need_error_newline) 158318334Speter { 158418334Speter fprintf (stderr, "\n"); 158518334Speter need_error_newline = 0; 158618334Speter } 158718334Speter 158818334Speter if (input_file_stack && input_file_stack->next != 0 158952558Sobrien && input_file_stack_tick != last_error_tick) 159018334Speter { 159118334Speter for (p = input_file_stack->next; p; p = p->next) 159252558Sobrien notice ((p == input_file_stack->next 159352558Sobrien ? "In file included from %s:%d" 159452558Sobrien : ",\n from %s:%d"), 159552558Sobrien p->name, p->line); 159618334Speter fprintf (stderr, ":\n"); 159718334Speter last_error_tick = input_file_stack_tick; 159818334Speter } 159952558Sobrien 160052558Sobrien (*print_error_function) (input_filename); 160118334Speter} 160218334Speter 160318334Speter/* Print a message. */ 160418334Speter 160518334Speterstatic void 160652558Sobrienvnotice (file, msgid, ap) 160752558Sobrien FILE *file; 160852558Sobrien char *msgid; 160918334Speter va_list ap; 161018334Speter{ 161152558Sobrien vfprintf (file, _(msgid), ap); 161252558Sobrien} 161318334Speter 161452558Sobrienvoid 161552558Sobriennotice VPROTO((const char *msgid, ...)) 161652558Sobrien{ 161752558Sobrien#ifndef ANSI_PROTOTYPES 161852558Sobrien char *msgid; 161952558Sobrien#endif 162052558Sobrien va_list ap; 162152558Sobrien 162252558Sobrien VA_START (ap, msgid); 162352558Sobrien 162452558Sobrien#ifndef ANSI_PROTOTYPES 162552558Sobrien msgid = va_arg (ap, char *); 162652558Sobrien#endif 162752558Sobrien 162852558Sobrien vnotice (stderr, msgid, ap); 162952558Sobrien va_end (ap); 163018334Speter} 163118334Speter 163252558Sobrienvoid 163352558Sobrienfnotice VPROTO((FILE *file, const char *msgid, ...)) 163452558Sobrien{ 163552558Sobrien#ifndef ANSI_PROTOTYPES 163652558Sobrien FILE *file; 163752558Sobrien const char *msgid; 163852558Sobrien#endif 163952558Sobrien va_list ap; 164018334Speter 164152558Sobrien VA_START (ap, msgid); 164252558Sobrien 164352558Sobrien#ifndef ANSI_PROTOTYPES 164452558Sobrien file = va_arg (ap, FILE *); 164552558Sobrien msgid = va_arg (ap, const char *); 164652558Sobrien#endif 164752558Sobrien 164852558Sobrien vnotice (file, msgid, ap); 164952558Sobrien va_end (ap); 165052558Sobrien} 165152558Sobrien 165252558Sobrien/* Report FILE and LINE (or program name), and optionally just WARN. */ 165352558Sobrien 165418334Speterstatic void 165552558Sobrienreport_file_and_line (file, line, warn) 165618334Speter char *file; 165718334Speter int line; 165852558Sobrien int warn; 165918334Speter{ 166018334Speter if (file) 166118334Speter fprintf (stderr, "%s:%d: ", file, line); 166218334Speter else 166318334Speter fprintf (stderr, "%s: ", progname); 166418334Speter 166552558Sobrien if (warn) 166652558Sobrien notice ("warning: "); 166752558Sobrien} 166852558Sobrien 166952558Sobrien/* Print a message. */ 167052558Sobrien 167152558Sobrienstatic void 167252558Sobrienvmessage (prefix, msgid, ap) 167352558Sobrien const char *prefix; 167452558Sobrien const char *msgid; 167552558Sobrien va_list ap; 167652558Sobrien{ 167752558Sobrien if (prefix) 167852558Sobrien fprintf (stderr, "%s: ", prefix); 167952558Sobrien 168052558Sobrien vfprintf (stderr, msgid, ap); 168152558Sobrien} 168252558Sobrien 168352558Sobrien/* Print a message relevant to line LINE of file FILE. */ 168452558Sobrien 168552558Sobrienstatic void 168652558Sobrienv_message_with_file_and_line (file, line, warn, msgid, ap) 168752558Sobrien const char *file; 168852558Sobrien int line; 168952558Sobrien int warn; 169052558Sobrien const char *msgid; 169152558Sobrien va_list ap; 169252558Sobrien{ 169352558Sobrien report_file_and_line (file, line, warn); 169452558Sobrien vnotice (stderr, msgid, ap); 169518334Speter fputc ('\n', stderr); 169618334Speter} 169718334Speter 169818334Speter/* Print a message relevant to the given DECL. */ 169918334Speter 170018334Speterstatic void 170152558Sobrienv_message_with_decl (decl, warn, msgid, ap) 170218334Speter tree decl; 170352558Sobrien int warn; 170452558Sobrien const char *msgid; 170518334Speter va_list ap; 170618334Speter{ 170752558Sobrien const char *p; 170818334Speter 170952558Sobrien report_file_and_line (DECL_SOURCE_FILE (decl), 171052558Sobrien DECL_SOURCE_LINE (decl), warn); 171118334Speter 171218334Speter /* Do magic to get around lack of varargs support for insertion 171318334Speter of arguments into existing list. We know that the decl is first; 171418334Speter we ass_u_me that it will be printed with "%s". */ 171518334Speter 171652558Sobrien for (p = _(msgid); *p; ++p) 171718334Speter { 171818334Speter if (*p == '%') 171918334Speter { 172018334Speter if (*(p + 1) == '%') 172118334Speter ++p; 172252558Sobrien else if (*(p + 1) != 's') 172352558Sobrien abort (); 172418334Speter else 172518334Speter break; 172618334Speter } 172718334Speter } 172818334Speter 172952558Sobrien if (p > _(msgid)) /* Print the left-hand substring. */ 173018334Speter { 173118334Speter char fmt[sizeof "%.255s"]; 173252558Sobrien long width = p - _(msgid); 173318334Speter 173418334Speter if (width > 255L) width = 255L; /* arbitrary */ 173518334Speter sprintf (fmt, "%%.%lds", width); 173652558Sobrien fprintf (stderr, fmt, _(msgid)); 173718334Speter } 173818334Speter 173918334Speter if (*p == '%') /* Print the name. */ 174018334Speter { 174152558Sobrien const char *n = (DECL_NAME (decl) 174250615Sobrien ? (*decl_printable_name) (decl, 2) 174318334Speter : "((anonymous))"); 174418334Speter fputs (n, stderr); 174518334Speter while (*p) 174618334Speter { 174718334Speter ++p; 174850615Sobrien if (ISALPHA (*(p - 1) & 0xFF)) 174918334Speter break; 175018334Speter } 175118334Speter } 175218334Speter 175318334Speter if (*p) /* Print the rest of the message. */ 175418334Speter vmessage ((char *)NULL, p, ap); 175518334Speter 175618334Speter fputc ('\n', stderr); 175718334Speter} 175818334Speter 175918334Speter/* Figure file and line of the given INSN. */ 176018334Speter 176118334Speterstatic void 176218334Speterfile_and_line_for_asm (insn, pfile, pline) 176318334Speter rtx insn; 176418334Speter char **pfile; 176518334Speter int *pline; 176618334Speter{ 176718334Speter rtx body = PATTERN (insn); 176818334Speter rtx asmop; 176918334Speter 177018334Speter /* Find the (or one of the) ASM_OPERANDS in the insn. */ 177118334Speter if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS) 177218334Speter asmop = SET_SRC (body); 177318334Speter else if (GET_CODE (body) == ASM_OPERANDS) 177418334Speter asmop = body; 177518334Speter else if (GET_CODE (body) == PARALLEL 177618334Speter && GET_CODE (XVECEXP (body, 0, 0)) == SET) 177718334Speter asmop = SET_SRC (XVECEXP (body, 0, 0)); 177818334Speter else if (GET_CODE (body) == PARALLEL 177918334Speter && GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS) 178018334Speter asmop = XVECEXP (body, 0, 0); 178118334Speter else 178218334Speter asmop = NULL; 178318334Speter 178418334Speter if (asmop) 178518334Speter { 178618334Speter *pfile = ASM_OPERANDS_SOURCE_FILE (asmop); 178718334Speter *pline = ASM_OPERANDS_SOURCE_LINE (asmop); 178818334Speter } 178918334Speter else 179018334Speter { 179118334Speter *pfile = input_filename; 179218334Speter *pline = lineno; 179318334Speter } 179418334Speter} 179518334Speter 179618334Speter/* Report an error at line LINE of file FILE. */ 179718334Speter 179818334Speterstatic void 179952558Sobrienv_error_with_file_and_line (file, line, msgid, ap) 180052558Sobrien const char *file; 180118334Speter int line; 180252558Sobrien const char *msgid; 180318334Speter va_list ap; 180418334Speter{ 180518334Speter count_error (0); 180618334Speter report_error_function (file); 180752558Sobrien v_message_with_file_and_line (file, line, 0, msgid, ap); 180818334Speter} 180918334Speter 181018334Spetervoid 181152558Sobrienerror_with_file_and_line VPROTO((const char *file, int line, 181252558Sobrien const char *msgid, ...)) 181318334Speter{ 181452558Sobrien#ifndef ANSI_PROTOTYPES 181552558Sobrien const char *file; 181618334Speter int line; 181752558Sobrien const char *msgid; 181818334Speter#endif 181918334Speter va_list ap; 182018334Speter 182152558Sobrien VA_START (ap, msgid); 182218334Speter 182352558Sobrien#ifndef ANSI_PROTOTYPES 182452558Sobrien file = va_arg (ap, const char *); 182518334Speter line = va_arg (ap, int); 182652558Sobrien msgid = va_arg (ap, const char *); 182718334Speter#endif 182818334Speter 182952558Sobrien v_error_with_file_and_line (file, line, msgid, ap); 183018334Speter va_end (ap); 183118334Speter} 183218334Speter 183318334Speter/* Report an error at the declaration DECL. 183452558Sobrien MSGID is a format string which uses %s to substitute the declaration 183518334Speter name; subsequent substitutions are a la printf. */ 183618334Speter 183718334Speterstatic void 183852558Sobrienv_error_with_decl (decl, msgid, ap) 183918334Speter tree decl; 184052558Sobrien const char *msgid; 184118334Speter va_list ap; 184218334Speter{ 184318334Speter count_error (0); 184418334Speter report_error_function (DECL_SOURCE_FILE (decl)); 184552558Sobrien v_message_with_decl (decl, 0, msgid, ap); 184618334Speter} 184718334Speter 184818334Spetervoid 184952558Sobrienerror_with_decl VPROTO((tree decl, const char *msgid, ...)) 185018334Speter{ 185152558Sobrien#ifndef ANSI_PROTOTYPES 185218334Speter tree decl; 185352558Sobrien const char *msgid; 185418334Speter#endif 185518334Speter va_list ap; 185618334Speter 185752558Sobrien VA_START (ap, msgid); 185818334Speter 185952558Sobrien#ifndef ANSI_PROTOTYPES 186018334Speter decl = va_arg (ap, tree); 186152558Sobrien msgid = va_arg (ap, const char *); 186218334Speter#endif 186318334Speter 186452558Sobrien v_error_with_decl (decl, msgid, ap); 186518334Speter va_end (ap); 186618334Speter} 186718334Speter 186818334Speter/* Report an error at the line number of the insn INSN. 186918334Speter This is used only when INSN is an `asm' with operands, 187018334Speter and each ASM_OPERANDS records its own source file and line. */ 187118334Speter 187218334Speterstatic void 187352558Sobrienv_error_for_asm (insn, msgid, ap) 187418334Speter rtx insn; 187552558Sobrien const char *msgid; 187618334Speter va_list ap; 187718334Speter{ 187818334Speter char *file; 187918334Speter int line; 188018334Speter 188118334Speter count_error (0); 188218334Speter file_and_line_for_asm (insn, &file, &line); 188318334Speter report_error_function (file); 188452558Sobrien v_message_with_file_and_line (file, line, 0, msgid, ap); 188518334Speter} 188618334Speter 188718334Spetervoid 188852558Sobrienerror_for_asm VPROTO((rtx insn, const char *msgid, ...)) 188918334Speter{ 189052558Sobrien#ifndef ANSI_PROTOTYPES 189118334Speter rtx insn; 189252558Sobrien const char *msgid; 189318334Speter#endif 189418334Speter va_list ap; 189518334Speter 189652558Sobrien VA_START (ap, msgid); 189718334Speter 189852558Sobrien#ifndef ANSI_PROTOTYPES 189918334Speter insn = va_arg (ap, rtx); 190052558Sobrien msgid = va_arg (ap, const char *); 190118334Speter#endif 190218334Speter 190352558Sobrien v_error_for_asm (insn, msgid, ap); 190418334Speter va_end (ap); 190518334Speter} 190618334Speter 190718334Speter/* Report an error at the current line number. */ 190818334Speter 190918334Speterstatic void 191052558Sobrienverror (msgid, ap) 191152558Sobrien const char *msgid; 191218334Speter va_list ap; 191318334Speter{ 191452558Sobrien v_error_with_file_and_line (input_filename, lineno, msgid, ap); 191518334Speter} 191618334Speter 191718334Spetervoid 191852558Sobrienerror VPROTO((const char *msgid, ...)) 191918334Speter{ 192052558Sobrien#ifndef ANSI_PROTOTYPES 192152558Sobrien const char *msgid; 192218334Speter#endif 192318334Speter va_list ap; 192418334Speter 192552558Sobrien VA_START (ap, msgid); 192618334Speter 192752558Sobrien#ifndef ANSI_PROTOTYPES 192852558Sobrien msgid = va_arg (ap, const char *); 192918334Speter#endif 193018334Speter 193152558Sobrien verror (msgid, ap); 193218334Speter va_end (ap); 193318334Speter} 193418334Speter 193518334Speter/* Report a fatal error at the current line number. */ 193618334Speter 193718334Speterstatic void 193852558Sobrienvfatal (msgid, ap) 193952558Sobrien const char *msgid; 194018334Speter va_list ap; 194118334Speter{ 194252558Sobrien verror (msgid, ap); 194318334Speter exit (FATAL_EXIT_CODE); 194418334Speter} 194518334Speter 194618334Spetervoid 194752558Sobrienfatal VPROTO((const char *msgid, ...)) 194818334Speter{ 194952558Sobrien#ifndef ANSI_PROTOTYPES 195052558Sobrien const char *msgid; 195118334Speter#endif 195218334Speter va_list ap; 195318334Speter 195452558Sobrien VA_START (ap, msgid); 195518334Speter 195652558Sobrien#ifndef ANSI_PROTOTYPES 195752558Sobrien msgid = va_arg (ap, const char *); 195818334Speter#endif 195918334Speter 196052558Sobrien vfatal (msgid, ap); 196118334Speter va_end (ap); 196218334Speter} 196318334Speter 196418334Speter/* Report a warning at line LINE of file FILE. */ 196518334Speter 196618334Speterstatic void 196752558Sobrienv_warning_with_file_and_line (file, line, msgid, ap) 196852558Sobrien const char *file; 196918334Speter int line; 197052558Sobrien const char *msgid; 197118334Speter va_list ap; 197218334Speter{ 197318334Speter if (count_error (1)) 197418334Speter { 197518334Speter report_error_function (file); 197652558Sobrien v_message_with_file_and_line (file, line, 1, msgid, ap); 197718334Speter } 197818334Speter} 197918334Speter 198018334Spetervoid 198152558Sobrienwarning_with_file_and_line VPROTO((const char *file, int line, 198252558Sobrien const char *msgid, ...)) 198318334Speter{ 198452558Sobrien#ifndef ANSI_PROTOTYPES 198552558Sobrien const char *file; 198618334Speter int line; 198752558Sobrien const char *msgid; 198818334Speter#endif 198918334Speter va_list ap; 199018334Speter 199152558Sobrien VA_START (ap, msgid); 199218334Speter 199352558Sobrien#ifndef ANSI_PROTOTYPES 199452558Sobrien file = va_arg (ap, const char *); 199518334Speter line = va_arg (ap, int); 199652558Sobrien msgid = va_arg (ap, const char *); 199718334Speter#endif 199818334Speter 199952558Sobrien v_warning_with_file_and_line (file, line, msgid, ap); 200018334Speter va_end (ap); 200118334Speter} 200218334Speter 200318334Speter/* Report a warning at the declaration DECL. 200452558Sobrien MSGID is a format string which uses %s to substitute the declaration 200518334Speter name; subsequent substitutions are a la printf. */ 200618334Speter 200718334Speterstatic void 200852558Sobrienv_warning_with_decl (decl, msgid, ap) 200918334Speter tree decl; 201052558Sobrien const char *msgid; 201118334Speter va_list ap; 201218334Speter{ 201318334Speter if (count_error (1)) 201418334Speter { 201518334Speter report_error_function (DECL_SOURCE_FILE (decl)); 201652558Sobrien v_message_with_decl (decl, 1, msgid, ap); 201718334Speter } 201818334Speter} 201918334Speter 202018334Spetervoid 202152558Sobrienwarning_with_decl VPROTO((tree decl, const char *msgid, ...)) 202218334Speter{ 202352558Sobrien#ifndef ANSI_PROTOTYPES 202418334Speter tree decl; 202552558Sobrien const char *msgid; 202618334Speter#endif 202718334Speter va_list ap; 202818334Speter 202952558Sobrien VA_START (ap, msgid); 203018334Speter 203152558Sobrien#ifndef ANSI_PROTOTYPES 203218334Speter decl = va_arg (ap, tree); 203352558Sobrien msgid = va_arg (ap, const char *); 203418334Speter#endif 203518334Speter 203652558Sobrien v_warning_with_decl (decl, msgid, ap); 203718334Speter va_end (ap); 203818334Speter} 203918334Speter 204018334Speter/* Report a warning at the line number of the insn INSN. 204118334Speter This is used only when INSN is an `asm' with operands, 204218334Speter and each ASM_OPERANDS records its own source file and line. */ 204318334Speter 204418334Speterstatic void 204552558Sobrienv_warning_for_asm (insn, msgid, ap) 204618334Speter rtx insn; 204752558Sobrien const char *msgid; 204818334Speter va_list ap; 204918334Speter{ 205018334Speter if (count_error (1)) 205118334Speter { 205218334Speter char *file; 205318334Speter int line; 205418334Speter 205518334Speter file_and_line_for_asm (insn, &file, &line); 205618334Speter report_error_function (file); 205752558Sobrien v_message_with_file_and_line (file, line, 1, msgid, ap); 205818334Speter } 205918334Speter} 206018334Speter 206118334Spetervoid 206252558Sobrienwarning_for_asm VPROTO((rtx insn, const char *msgid, ...)) 206318334Speter{ 206452558Sobrien#ifndef ANSI_PROTOTYPES 206518334Speter rtx insn; 206652558Sobrien const char *msgid; 206718334Speter#endif 206818334Speter va_list ap; 206918334Speter 207052558Sobrien VA_START (ap, msgid); 207118334Speter 207252558Sobrien#ifndef ANSI_PROTOTYPES 207318334Speter insn = va_arg (ap, rtx); 207452558Sobrien msgid = va_arg (ap, const char *); 207518334Speter#endif 207618334Speter 207752558Sobrien v_warning_for_asm (insn, msgid, ap); 207818334Speter va_end (ap); 207918334Speter} 208018334Speter 208118334Speter/* Report a warning at the current line number. */ 208218334Speter 208318334Speterstatic void 208452558Sobrienvwarning (msgid, ap) 208552558Sobrien const char *msgid; 208618334Speter va_list ap; 208718334Speter{ 208852558Sobrien v_warning_with_file_and_line (input_filename, lineno, msgid, ap); 208918334Speter} 209018334Speter 209118334Spetervoid 209252558Sobrienwarning VPROTO((const char *msgid, ...)) 209318334Speter{ 209452558Sobrien#ifndef ANSI_PROTOTYPES 209552558Sobrien const char *msgid; 209618334Speter#endif 209718334Speter va_list ap; 209818334Speter 209952558Sobrien VA_START (ap, msgid); 210018334Speter 210152558Sobrien#ifndef ANSI_PROTOTYPES 210252558Sobrien msgid = va_arg (ap, const char *); 210318334Speter#endif 210418334Speter 210552558Sobrien vwarning (msgid, ap); 210618334Speter va_end (ap); 210718334Speter} 210818334Speter 210918334Speter/* These functions issue either warnings or errors depending on 211018334Speter -pedantic-errors. */ 211118334Speter 211218334Speterstatic void 211352558Sobrienvpedwarn (msgid, ap) 211452558Sobrien const char *msgid; 211518334Speter va_list ap; 211618334Speter{ 211718334Speter if (flag_pedantic_errors) 211852558Sobrien verror (msgid, ap); 211918334Speter else 212052558Sobrien vwarning (msgid, ap); 212118334Speter} 212218334Speter 212318334Spetervoid 212452558Sobrienpedwarn VPROTO((const char *msgid, ...)) 212518334Speter{ 212652558Sobrien#ifndef ANSI_PROTOTYPES 212752558Sobrien const char *msgid; 212818334Speter#endif 212918334Speter va_list ap; 213018334Speter 213152558Sobrien VA_START (ap, msgid); 213218334Speter 213352558Sobrien#ifndef ANSI_PROTOTYPES 213452558Sobrien msgid = va_arg (ap, const char *); 213518334Speter#endif 213618334Speter 213752558Sobrien vpedwarn (msgid, ap); 213818334Speter va_end (ap); 213918334Speter} 214018334Speter 214118334Speterstatic void 214252558Sobrienv_pedwarn_with_decl (decl, msgid, ap) 214318334Speter tree decl; 214452558Sobrien const char *msgid; 214518334Speter va_list ap; 214618334Speter{ 214718334Speter /* We don't want -pedantic-errors to cause the compilation to fail from 214818334Speter "errors" in system header files. Sometimes fixincludes can't fix what's 214918334Speter broken (eg: unsigned char bitfields - fixing it may change the alignment 215018334Speter which will cause programs to mysteriously fail because the C library 215118334Speter or kernel uses the original layout). There's no point in issuing a 215218334Speter warning either, it's just unnecessary noise. */ 215318334Speter 215418334Speter if (! DECL_IN_SYSTEM_HEADER (decl)) 215518334Speter { 215618334Speter if (flag_pedantic_errors) 215752558Sobrien v_error_with_decl (decl, msgid, ap); 215818334Speter else 215952558Sobrien v_warning_with_decl (decl, msgid, ap); 216018334Speter } 216118334Speter} 216218334Speter 216318334Spetervoid 216452558Sobrienpedwarn_with_decl VPROTO((tree decl, const char *msgid, ...)) 216518334Speter{ 216652558Sobrien#ifndef ANSI_PROTOTYPES 216718334Speter tree decl; 216852558Sobrien const char *msgid; 216918334Speter#endif 217018334Speter va_list ap; 217118334Speter 217252558Sobrien VA_START (ap, msgid); 217318334Speter 217452558Sobrien#ifndef ANSI_PROTOTYPES 217518334Speter decl = va_arg (ap, tree); 217652558Sobrien msgid = va_arg (ap, const char *); 217718334Speter#endif 217818334Speter 217952558Sobrien v_pedwarn_with_decl (decl, msgid, ap); 218018334Speter va_end (ap); 218118334Speter} 218218334Speter 218318334Speterstatic void 218452558Sobrienv_pedwarn_with_file_and_line (file, line, msgid, ap) 218552558Sobrien const char *file; 218618334Speter int line; 218752558Sobrien const char *msgid; 218818334Speter va_list ap; 218918334Speter{ 219018334Speter if (flag_pedantic_errors) 219152558Sobrien v_error_with_file_and_line (file, line, msgid, ap); 219218334Speter else 219352558Sobrien v_warning_with_file_and_line (file, line, msgid, ap); 219418334Speter} 219518334Speter 219618334Spetervoid 219752558Sobrienpedwarn_with_file_and_line VPROTO((const char *file, int line, 219852558Sobrien const char *msgid, ...)) 219918334Speter{ 220052558Sobrien#ifndef ANSI_PROTOTYPES 220152558Sobrien const char *file; 220218334Speter int line; 220352558Sobrien const char *msgid; 220418334Speter#endif 220518334Speter va_list ap; 220618334Speter 220752558Sobrien VA_START (ap, msgid); 220818334Speter 220952558Sobrien#ifndef ANSI_PROTOTYPES 221052558Sobrien file = va_arg (ap, const char *); 221118334Speter line = va_arg (ap, int); 221252558Sobrien msgid = va_arg (ap, const char *); 221318334Speter#endif 221418334Speter 221552558Sobrien v_pedwarn_with_file_and_line (file, line, msgid, ap); 221618334Speter va_end (ap); 221718334Speter} 221818334Speter 221918334Speter/* Apologize for not implementing some feature. */ 222018334Speter 222118334Speterstatic void 222252558Sobrienvsorry (msgid, ap) 222352558Sobrien const char *msgid; 222418334Speter va_list ap; 222518334Speter{ 222618334Speter sorrycount++; 222718334Speter if (input_filename) 222818334Speter fprintf (stderr, "%s:%d: ", input_filename, lineno); 222918334Speter else 223018334Speter fprintf (stderr, "%s: ", progname); 223152558Sobrien notice ("sorry, not implemented: "); 223252558Sobrien vnotice (stderr, msgid, ap); 223318334Speter fputc ('\n', stderr); 223418334Speter} 223518334Speter 223618334Spetervoid 223752558Sobriensorry VPROTO((const char *msgid, ...)) 223818334Speter{ 223952558Sobrien#ifndef ANSI_PROTOTYPES 224052558Sobrien const char *msgid; 224118334Speter#endif 224218334Speter va_list ap; 224318334Speter 224452558Sobrien VA_START (ap, msgid); 224518334Speter 224652558Sobrien#ifndef ANSI_PROTOTYPES 224752558Sobrien msgid = va_arg (ap, const char *); 224818334Speter#endif 224918334Speter 225052558Sobrien vsorry (msgid, ap); 225118334Speter va_end (ap); 225218334Speter} 225352558Sobrien 225452558Sobrien/* Given a partial pathname as input, return another pathname that shares 225552558Sobrien no elements with the pathname of __FILE__. This is used by abort() to 225652558Sobrien print `Internal compiler error in expr.c' instead of `Internal compiler 225752558Sobrien error in ../../egcs/gcc/expr.c'. */ 225852558Sobrienconst char * 225952558Sobrientrim_filename (name) 226052558Sobrien const char *name; 226118334Speter{ 226252558Sobrien static const char *this_file = __FILE__; 226352558Sobrien const char *p = name, *q = this_file; 226418334Speter 226552558Sobrien while (*p == *q && *p != 0 && *q != 0) p++, q++; 226652558Sobrien while (p > name && p[-1] != DIR_SEPARATOR 226752558Sobrien#ifdef DIR_SEPARATOR_2 226852558Sobrien && p[-1] != DIR_SEPARATOR_2 226918334Speter#endif 227052558Sobrien ) 227152558Sobrien p--; 227218334Speter 227352558Sobrien return p; 227452558Sobrien} 227518334Speter 227618334Speter/* More 'friendly' abort that prints the line and file. 227718334Speter config.h can #define abort fancy_abort if you like that sort of thing. 227818334Speter 227918334Speter I don't think this is actually a good idea. 228018334Speter Other sorts of crashes will look a certain way. 228118334Speter It is a good thing if crashes from calling abort look the same way. 228218334Speter -- RMS */ 228318334Speter 228418334Spetervoid 228518334Speterfancy_abort () 228618334Speter{ 228718334Speter fatal ("internal gcc abort"); 228818334Speter} 228918334Speter 229018334Speter/* This calls abort and is used to avoid problems when abort if a macro. 229118334Speter It is used when we need to pass the address of abort. */ 229218334Speter 229318334Spetervoid 229418334Speterdo_abort () 229518334Speter{ 229618334Speter abort (); 229718334Speter} 229818334Speter 229918334Speter/* When `malloc.c' is compiled with `rcheck' defined, 230018334Speter it calls this function to report clobberage. */ 230118334Speter 230218334Spetervoid 230318334Speterbotch (s) 230452558Sobrien const char * s ATTRIBUTE_UNUSED; 230518334Speter{ 230618334Speter abort (); 230718334Speter} 230818334Speter 230918334Speter/* Same as `malloc' but report error if no memory available. */ 231018334Speter 231152558SobrienPTR 231218334Speterxmalloc (size) 231352558Sobrien size_t size; 231418334Speter{ 231552558Sobrien register PTR value; 231650615Sobrien 231750615Sobrien if (size == 0) 231850615Sobrien size = 1; 231950615Sobrien 232052558Sobrien value = (PTR) malloc (size); 232118334Speter if (value == 0) 232218334Speter fatal ("virtual memory exhausted"); 232318334Speter return value; 232418334Speter} 232518334Speter 232650615Sobrien/* Same as `calloc' but report error if no memory available. */ 232718334Speter 232852558SobrienPTR 232950615Sobrienxcalloc (size1, size2) 233052558Sobrien size_t size1, size2; 233150615Sobrien{ 233252558Sobrien register PTR value; 233350615Sobrien 233450615Sobrien if (size1 == 0 || size2 == 0) 233550615Sobrien size1 = size2 = 1; 233650615Sobrien 233752558Sobrien value = (PTR) calloc (size1, size2); 233850615Sobrien if (value == 0) 233950615Sobrien fatal ("virtual memory exhausted"); 234050615Sobrien return value; 234150615Sobrien} 234250615Sobrien 234350615Sobrien 234450615Sobrien/* Same as `realloc' but report error if no memory available. 234550615Sobrien Also handle null PTR even if the vendor realloc gets it wrong. */ 234650615Sobrien 234752558SobrienPTR 234818334Speterxrealloc (ptr, size) 234952558Sobrien PTR ptr; 235052558Sobrien size_t size; 235118334Speter{ 235252558Sobrien register PTR result; 235350615Sobrien 235450615Sobrien if (size == 0) 235550615Sobrien size = 1; 235650615Sobrien 235752558Sobrien result = (ptr ? (PTR) realloc (ptr, size) : (PTR) malloc (size)); 235850615Sobrien 235918334Speter if (!result) 236018334Speter fatal ("virtual memory exhausted"); 236150615Sobrien 236218334Speter return result; 236318334Speter} 236450615Sobrien 236550615Sobrien/* Same as `strdup' but report error if no memory available. */ 236650615Sobrien 236750615Sobrienchar * 236850615Sobrienxstrdup (s) 236952558Sobrien register const char *s; 237050615Sobrien{ 237150615Sobrien register char *result = (char *) malloc (strlen (s) + 1); 237250615Sobrien 237350615Sobrien if (! result) 237450615Sobrien fatal ("virtual memory exhausted"); 237550615Sobrien strcpy (result, s); 237650615Sobrien return result; 237750615Sobrien} 237818334Speter 237918334Speter/* Return the logarithm of X, base 2, considering X unsigned, 238018334Speter if X is a power of 2. Otherwise, returns -1. 238118334Speter 238218334Speter This should be used via the `exact_log2' macro. */ 238318334Speter 238418334Speterint 238518334Speterexact_log2_wide (x) 238618334Speter register unsigned HOST_WIDE_INT x; 238718334Speter{ 238818334Speter register int log = 0; 238918334Speter /* Test for 0 or a power of 2. */ 239018334Speter if (x == 0 || x != (x & -x)) 239118334Speter return -1; 239218334Speter while ((x >>= 1) != 0) 239318334Speter log++; 239418334Speter return log; 239518334Speter} 239618334Speter 239718334Speter/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X. 239818334Speter If X is 0, return -1. 239918334Speter 240018334Speter This should be used via the floor_log2 macro. */ 240118334Speter 240218334Speterint 240318334Speterfloor_log2_wide (x) 240418334Speter register unsigned HOST_WIDE_INT x; 240518334Speter{ 240618334Speter register int log = -1; 240718334Speter while (x != 0) 240818334Speter log++, 240918334Speter x >>= 1; 241018334Speter return log; 241118334Speter} 241218334Speter 241350615Sobrienstatic int float_handler_set; 241418334Speterint float_handled; 241518334Speterjmp_buf float_handler; 241618334Speter 241750615Sobrien/* Signals actually come here. */ 241850615Sobrien 241950615Sobrienstatic void 242050615Sobrienfloat_signal (signo) 242150615Sobrien /* If this is missing, some compilers complain. */ 242250615Sobrien int signo ATTRIBUTE_UNUSED; 242350615Sobrien{ 242450615Sobrien if (float_handled == 0) 242550615Sobrien abort (); 242650615Sobrien#if defined (USG) || defined (hpux) 242750615Sobrien signal (SIGFPE, float_signal); /* re-enable the signal catcher */ 242850615Sobrien#endif 242950615Sobrien float_handled = 0; 243050615Sobrien signal (SIGFPE, float_signal); 243150615Sobrien longjmp (float_handler, 1); 243250615Sobrien} 243350615Sobrien 243418334Speter/* Specify where to longjmp to when a floating arithmetic error happens. 243518334Speter If HANDLER is 0, it means don't handle the errors any more. */ 243618334Speter 243718334Spetervoid 243818334Speterset_float_handler (handler) 243918334Speter jmp_buf handler; 244018334Speter{ 244118334Speter float_handled = (handler != 0); 244218334Speter if (handler) 244318334Speter bcopy ((char *) handler, (char *) float_handler, sizeof (float_handler)); 244450615Sobrien 244550615Sobrien if (float_handled && ! float_handler_set) 244650615Sobrien { 244750615Sobrien signal (SIGFPE, float_signal); 244850615Sobrien float_handler_set = 1; 244950615Sobrien } 245018334Speter} 245118334Speter 245252558Sobrien/* This is a wrapper function for code which might elicit an 245352558Sobrien arithmetic exception. That code should be passed in as a function 245452558Sobrien pointer FN, and one argument DATA. DATA is usually a struct which 245552558Sobrien contains the real input and output for function FN. This function 245652558Sobrien returns 0 (failure) if longjmp was called (i.e. an exception 245752558Sobrien occured.) It returns 1 (success) otherwise. */ 245852558Sobrien 245952558Sobrienint 246052558Sobriendo_float_handler (fn, data) 246152558Sobrien void (*fn) PROTO ((PTR)); 246252558Sobrien PTR data; 246352558Sobrien{ 246452558Sobrien jmp_buf buf; 246552558Sobrien 246652558Sobrien if (setjmp (buf)) 246752558Sobrien { 246852558Sobrien /* We got here via longjmp() caused by an exception in function fn() */ 246952558Sobrien set_float_handler (NULL); 247052558Sobrien return 0; 247152558Sobrien } 247252558Sobrien 247352558Sobrien set_float_handler (buf); 247452558Sobrien (*fn)(data); 247552558Sobrien set_float_handler (NULL); 247652558Sobrien return 1; 247752558Sobrien} 247852558Sobrien 247918334Speter/* Specify, in HANDLER, where to longjmp to when a floating arithmetic 248018334Speter error happens, pushing the previous specification into OLD_HANDLER. 248118334Speter Return an indication of whether there was a previous handler in effect. */ 248218334Speter 248318334Speterint 248418334Speterpush_float_handler (handler, old_handler) 248518334Speter jmp_buf handler, old_handler; 248618334Speter{ 248718334Speter int was_handled = float_handled; 248818334Speter 248918334Speter float_handled = 1; 249018334Speter if (was_handled) 249152558Sobrien memcpy ((char *) old_handler, (char *) float_handler, 249218334Speter sizeof (float_handler)); 249318334Speter 249452558Sobrien memcpy ((char *) float_handler, (char *) handler, sizeof (float_handler)); 249518334Speter return was_handled; 249618334Speter} 249718334Speter 249818334Speter/* Restore the previous specification of whether and where to longjmp to 249918334Speter when a floating arithmetic error happens. */ 250018334Speter 250118334Spetervoid 250218334Speterpop_float_handler (handled, handler) 250318334Speter int handled; 250418334Speter jmp_buf handler; 250518334Speter{ 250618334Speter float_handled = handled; 250718334Speter if (handled) 250818334Speter bcopy ((char *) handler, (char *) float_handler, sizeof (float_handler)); 250918334Speter} 251018334Speter 251118334Speter/* Handler for SIGPIPE. */ 251218334Speter 251318334Speterstatic void 251418334Speterpipe_closed (signo) 251518334Speter /* If this is missing, some compilers complain. */ 251650615Sobrien int signo ATTRIBUTE_UNUSED; 251718334Speter{ 251818334Speter fatal ("output pipe has been closed"); 251918334Speter} 252018334Speter 252118334Speter/* Strip off a legitimate source ending from the input string NAME of 252218334Speter length LEN. Rather than having to know the names used by all of 252350615Sobrien our front ends, we strip off an ending of a period followed by 252450615Sobrien up to five characters. (Java uses ".class".) */ 252518334Speter 252618334Spetervoid 252718334Speterstrip_off_ending (name, len) 252818334Speter char *name; 252918334Speter int len; 253018334Speter{ 253150615Sobrien int i; 253250615Sobrien for (i = 2; i < 6 && len > i; i++) 253350615Sobrien { 253450615Sobrien if (name[len - i] == '.') 253550615Sobrien { 253650615Sobrien name[len - i] = '\0'; 253750615Sobrien break; 253850615Sobrien } 253950615Sobrien } 254018334Speter} 254118334Speter 254218334Speter/* Output a quoted string. */ 254350615Sobrien 254418334Spetervoid 254518334Speteroutput_quoted_string (asm_file, string) 254618334Speter FILE *asm_file; 254752558Sobrien const char *string; 254818334Speter{ 254950615Sobrien#ifdef OUTPUT_QUOTED_STRING 255050615Sobrien OUTPUT_QUOTED_STRING (asm_file, string); 255150615Sobrien#else 255218334Speter char c; 255318334Speter 255418334Speter putc ('\"', asm_file); 255518334Speter while ((c = *string++) != 0) 255618334Speter { 255718334Speter if (c == '\"' || c == '\\') 255818334Speter putc ('\\', asm_file); 255918334Speter putc (c, asm_file); 256018334Speter } 256118334Speter putc ('\"', asm_file); 256250615Sobrien#endif 256318334Speter} 256418334Speter 256518334Speter/* Output a file name in the form wanted by System V. */ 256618334Speter 256718334Spetervoid 256818334Speteroutput_file_directive (asm_file, input_name) 256918334Speter FILE *asm_file; 257052558Sobrien const char *input_name; 257118334Speter{ 257218334Speter int len = strlen (input_name); 257352558Sobrien const char *na = input_name + len; 257418334Speter 257518334Speter /* NA gets INPUT_NAME sans directory names. */ 257618334Speter while (na > input_name) 257718334Speter { 257818334Speter if (na[-1] == '/') 257918334Speter break; 258052558Sobrien#ifdef DIR_SEPARATOR 258152558Sobrien if (na[-1] == DIR_SEPARATOR) 258252558Sobrien break; 258352558Sobrien#endif 258418334Speter na--; 258518334Speter } 258618334Speter 258718334Speter#ifdef ASM_OUTPUT_MAIN_SOURCE_FILENAME 258818334Speter ASM_OUTPUT_MAIN_SOURCE_FILENAME (asm_file, na); 258918334Speter#else 259018334Speter#ifdef ASM_OUTPUT_SOURCE_FILENAME 259118334Speter ASM_OUTPUT_SOURCE_FILENAME (asm_file, na); 259218334Speter#else 259318334Speter fprintf (asm_file, "\t.file\t"); 259418334Speter output_quoted_string (asm_file, na); 259518334Speter fputc ('\n', asm_file); 259618334Speter#endif 259718334Speter#endif 259818334Speter} 259918334Speter 260052558Sobrien#ifdef ASM_IDENTIFY_LANGUAGE 260150615Sobrien/* Routine to build language identifier for object file. */ 260218334Speterstatic void 260318334Speteroutput_lang_identify (asm_out_file) 260418334Speter FILE *asm_out_file; 260518334Speter{ 260618334Speter int len = strlen (lang_identify ()) + sizeof ("__gnu_compiled_") + 1; 260718334Speter char *s = (char *) alloca (len); 260818334Speter sprintf (s, "__gnu_compiled_%s", lang_identify ()); 260918334Speter ASM_OUTPUT_LABEL (asm_out_file, s); 261018334Speter} 261152558Sobrien#endif 261218334Speter 261318334Speter/* Routine to open a dump file. */ 261450615Sobrienstatic void 261550615Sobrienopen_dump_file (suffix, function_name) 261652558Sobrien const char *suffix; 261752558Sobrien const char *function_name; 261818334Speter{ 261950615Sobrien char *dumpname; 262018334Speter 262150615Sobrien TIMEVAR 262250615Sobrien (dump_time, 262350615Sobrien { 262450615Sobrien dumpname = (char *) xmalloc (strlen (dump_base_name) + strlen (suffix) + 1); 262550615Sobrien 262650615Sobrien if (rtl_dump_file != NULL) 262750615Sobrien fclose (rtl_dump_file); 262850615Sobrien 262950615Sobrien strcpy (dumpname, dump_base_name); 263050615Sobrien strcat (dumpname, suffix); 263150615Sobrien 263250615Sobrien rtl_dump_file = fopen (dumpname, "a"); 263350615Sobrien 263450615Sobrien if (rtl_dump_file == NULL) 263550615Sobrien pfatal_with_name (dumpname); 263650615Sobrien 263750615Sobrien free (dumpname); 263850615Sobrien 263950615Sobrien if (function_name) 264050615Sobrien fprintf (rtl_dump_file, "\n;; Function %s\n\n", function_name); 264150615Sobrien }); 264250615Sobrien 264350615Sobrien return; 264450615Sobrien} 264550615Sobrien 264650615Sobrien/* Routine to close a dump file. */ 264750615Sobrienstatic void 264850615Sobrienclose_dump_file (func, insns) 264950615Sobrien void (*func) PROTO ((FILE *, rtx)); 265050615Sobrien rtx insns; 265150615Sobrien{ 265250615Sobrien TIMEVAR 265350615Sobrien (dump_time, 265450615Sobrien { 265550615Sobrien if (func) 265650615Sobrien func (rtl_dump_file, insns); 265750615Sobrien 265850615Sobrien fflush (rtl_dump_file); 265950615Sobrien fclose (rtl_dump_file); 266050615Sobrien 266150615Sobrien rtl_dump_file = NULL; 266250615Sobrien }); 266350615Sobrien 266450615Sobrien return; 266550615Sobrien} 266650615Sobrien 266750615Sobrien/* Routine to dump rtl into a file. */ 266850615Sobrienstatic void 266950615Sobriendump_rtl (suffix, decl, func, insns) 267052558Sobrien const char *suffix; 267150615Sobrien tree decl; 267250615Sobrien void (*func) PROTO ((FILE *, rtx)); 267350615Sobrien rtx insns; 267450615Sobrien{ 267550615Sobrien open_dump_file (suffix, decl_printable_name (decl, 2)); 267650615Sobrien close_dump_file (func, insns); 267750615Sobrien} 267850615Sobrien 267950615Sobrien/* Routine to empty a dump file. */ 268050615Sobrienstatic void 268150615Sobrienclean_dump_file (suffix) 268252558Sobrien const char *suffix; 268350615Sobrien{ 268452558Sobrien char *dumpname; 268550615Sobrien 268650615Sobrien dumpname = (char *) xmalloc (strlen (dump_base_name) + strlen (suffix) + 1); 268750615Sobrien 268850615Sobrien strcpy (dumpname, dump_base_name); 268918334Speter strcat (dumpname, suffix); 269050615Sobrien 269150615Sobrien rtl_dump_file = fopen (dumpname, "w"); 269250615Sobrien 269350615Sobrien if (rtl_dump_file == NULL) 269450615Sobrien pfatal_with_name (dumpname); 269550615Sobrien 269650615Sobrien free (dumpname); 269750615Sobrien 269850615Sobrien fclose (rtl_dump_file); 269950615Sobrien rtl_dump_file = NULL; 270050615Sobrien 270150615Sobrien return; 270218334Speter} 270318334Speter 270452558Sobrien/* Do any final processing required for the declarations in VEC, of 270552558Sobrien which there are LEN. We write out inline functions and variables 270652558Sobrien that have been deferred until this point, but which are required. 270752558Sobrien Returns non-zero if anything was put out. */ 270852558Sobrienint 270952558Sobrienwrapup_global_declarations (vec, len) 271052558Sobrien tree *vec; 271152558Sobrien int len; 271252558Sobrien{ 271352558Sobrien tree decl; 271452558Sobrien int i; 271552558Sobrien int reconsider; 271652558Sobrien int output_something = 0; 271750615Sobrien 271852558Sobrien for (i = 0; i < len; i++) 271952558Sobrien { 272052558Sobrien decl = vec[i]; 272152558Sobrien 272252558Sobrien /* We're not deferring this any longer. */ 272352558Sobrien DECL_DEFER_OUTPUT (decl) = 0; 272452558Sobrien 272552558Sobrien if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0 272652558Sobrien && incomplete_decl_finalize_hook != 0) 272752558Sobrien (*incomplete_decl_finalize_hook) (decl); 272852558Sobrien } 272952558Sobrien 273052558Sobrien /* Now emit any global variables or functions that we have been 273152558Sobrien putting off. We need to loop in case one of the things emitted 273252558Sobrien here references another one which comes earlier in the list. */ 273352558Sobrien do 273452558Sobrien { 273552558Sobrien reconsider = 0; 273652558Sobrien for (i = 0; i < len; i++) 273752558Sobrien { 273852558Sobrien decl = vec[i]; 273952558Sobrien 274052558Sobrien if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl)) 274152558Sobrien continue; 274252558Sobrien 274352558Sobrien /* Don't write out static consts, unless we still need them. 274452558Sobrien 274552558Sobrien We also keep static consts if not optimizing (for debugging), 274652558Sobrien unless the user specified -fno-keep-static-consts. 274752558Sobrien ??? They might be better written into the debug information. 274852558Sobrien This is possible when using DWARF. 274952558Sobrien 275052558Sobrien A language processor that wants static constants to be always 275152558Sobrien written out (even if it is not used) is responsible for 275252558Sobrien calling rest_of_decl_compilation itself. E.g. the C front-end 275352558Sobrien calls rest_of_decl_compilation from finish_decl. 275452558Sobrien One motivation for this is that is conventional in some 275552558Sobrien environments to write things like: 275652558Sobrien static const char rcsid[] = "... version string ..."; 275752558Sobrien intending to force the string to be in the executable. 275852558Sobrien 275952558Sobrien A language processor that would prefer to have unneeded 276052558Sobrien static constants "optimized away" would just defer writing 276152558Sobrien them out until here. E.g. C++ does this, because static 276252558Sobrien constants are often defined in header files. 276352558Sobrien 276452558Sobrien ??? A tempting alternative (for both C and C++) would be 276552558Sobrien to force a constant to be written if and only if it is 276652558Sobrien defined in a main file, as opposed to an include file. */ 276752558Sobrien 276852558Sobrien if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl) 276952558Sobrien && (! TREE_READONLY (decl) 277052558Sobrien || TREE_PUBLIC (decl) 277152558Sobrien || (!optimize && flag_keep_static_consts) 277252558Sobrien || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))) 277352558Sobrien { 277452558Sobrien reconsider = 1; 277552558Sobrien rest_of_decl_compilation (decl, NULL_PTR, 1, 1); 277652558Sobrien } 277752558Sobrien 277852558Sobrien if (TREE_CODE (decl) == FUNCTION_DECL 277952558Sobrien && DECL_INITIAL (decl) != 0 278052558Sobrien && DECL_SAVED_INSNS (decl) != 0 278152558Sobrien && (flag_keep_inline_functions 278252558Sobrien || (TREE_PUBLIC (decl) && !DECL_COMDAT (decl)) 278352558Sobrien || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))) 278452558Sobrien { 278552558Sobrien reconsider = 1; 278652558Sobrien temporary_allocation (); 278752558Sobrien output_inline_function (decl); 278852558Sobrien permanent_allocation (1); 278952558Sobrien } 279052558Sobrien } 279152558Sobrien 279252558Sobrien if (reconsider) 279352558Sobrien output_something = 1; 279452558Sobrien } 279552558Sobrien while (reconsider); 279652558Sobrien 279752558Sobrien return output_something; 279852558Sobrien} 279952558Sobrien 280052558Sobrien/* Issue appropriate warnings for the global declarations in VEC (of 280152558Sobrien which there are LEN). Output debugging information for them. */ 280252558Sobrienvoid 280352558Sobriencheck_global_declarations (vec, len) 280452558Sobrien tree *vec; 280552558Sobrien int len; 280652558Sobrien{ 280752558Sobrien tree decl; 280852558Sobrien int i; 280952558Sobrien 281052558Sobrien for (i = 0; i < len; i++) 281152558Sobrien { 281252558Sobrien decl = vec[i]; 281352558Sobrien 281452558Sobrien if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl) 281552558Sobrien && ! TREE_ASM_WRITTEN (decl)) 281652558Sobrien /* Cancel the RTL for this decl so that, if debugging info 281752558Sobrien output for global variables is still to come, 281852558Sobrien this one will be omitted. */ 281952558Sobrien DECL_RTL (decl) = NULL; 282052558Sobrien 282152558Sobrien /* Warn about any function 282252558Sobrien declared static but not defined. 282352558Sobrien We don't warn about variables, 282452558Sobrien because many programs have static variables 282552558Sobrien that exist only to get some text into the object file. */ 282652558Sobrien if (TREE_CODE (decl) == FUNCTION_DECL 282752558Sobrien && (warn_unused 282852558Sobrien || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) 282952558Sobrien && DECL_INITIAL (decl) == 0 283052558Sobrien && DECL_EXTERNAL (decl) 283152558Sobrien && ! DECL_ARTIFICIAL (decl) 283252558Sobrien && ! TREE_PUBLIC (decl)) 283352558Sobrien { 283452558Sobrien if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) 283552558Sobrien pedwarn_with_decl (decl, 283652558Sobrien "`%s' used but never defined"); 283752558Sobrien else 283852558Sobrien warning_with_decl (decl, 283952558Sobrien "`%s' declared `static' but never defined"); 284052558Sobrien /* This symbol is effectively an "extern" declaration now. */ 284152558Sobrien TREE_PUBLIC (decl) = 1; 284252558Sobrien assemble_external (decl); 284352558Sobrien } 284452558Sobrien 284552558Sobrien /* Warn about static fns or vars defined but not used, 284652558Sobrien but not about inline functions or static consts 284752558Sobrien since defining those in header files is normal practice. */ 284852558Sobrien if (warn_unused 284952558Sobrien && ((TREE_CODE (decl) == FUNCTION_DECL && ! DECL_INLINE (decl)) 285052558Sobrien || (TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl))) 285152558Sobrien && ! DECL_IN_SYSTEM_HEADER (decl) 285252558Sobrien && ! DECL_EXTERNAL (decl) 285352558Sobrien && ! TREE_PUBLIC (decl) 285452558Sobrien && ! TREE_USED (decl) 285552558Sobrien && (TREE_CODE (decl) == FUNCTION_DECL || ! DECL_REGISTER (decl)) 285652558Sobrien /* The TREE_USED bit for file-scope decls 285752558Sobrien is kept in the identifier, to handle multiple 285852558Sobrien external decls in different scopes. */ 285952558Sobrien && ! TREE_USED (DECL_NAME (decl))) 286052558Sobrien warning_with_decl (decl, "`%s' defined but not used"); 286152558Sobrien 286252558Sobrien#ifdef SDB_DEBUGGING_INFO 286352558Sobrien /* The COFF linker can move initialized global vars to the end. 286452558Sobrien And that can screw up the symbol ordering. 286552558Sobrien By putting the symbols in that order to begin with, 286652558Sobrien we avoid a problem. mcsun!unido!fauern!tumuc!pes@uunet.uu.net. */ 286752558Sobrien if (write_symbols == SDB_DEBUG && TREE_CODE (decl) == VAR_DECL 286852558Sobrien && TREE_PUBLIC (decl) && DECL_INITIAL (decl) 286952558Sobrien && ! DECL_EXTERNAL (decl) 287052558Sobrien && DECL_RTL (decl) != 0) 287152558Sobrien TIMEVAR (symout_time, sdbout_symbol (decl, 0)); 287252558Sobrien 287352558Sobrien /* Output COFF information for non-global 287452558Sobrien file-scope initialized variables. */ 287552558Sobrien if (write_symbols == SDB_DEBUG 287652558Sobrien && TREE_CODE (decl) == VAR_DECL 287752558Sobrien && DECL_INITIAL (decl) 287852558Sobrien && ! DECL_EXTERNAL (decl) 287952558Sobrien && DECL_RTL (decl) != 0 288052558Sobrien && GET_CODE (DECL_RTL (decl)) == MEM) 288152558Sobrien TIMEVAR (symout_time, sdbout_toplevel_data (decl)); 288252558Sobrien#endif /* SDB_DEBUGGING_INFO */ 288352558Sobrien#ifdef DWARF_DEBUGGING_INFO 288452558Sobrien /* Output DWARF information for file-scope tentative data object 288552558Sobrien declarations, file-scope (extern) function declarations (which 288652558Sobrien had no corresponding body) and file-scope tagged type declarations 288752558Sobrien and definitions which have not yet been forced out. */ 288852558Sobrien 288952558Sobrien if (write_symbols == DWARF_DEBUG 289052558Sobrien && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl))) 289152558Sobrien TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 1)); 289252558Sobrien#endif 289352558Sobrien#ifdef DWARF2_DEBUGGING_INFO 289452558Sobrien /* Output DWARF2 information for file-scope tentative data object 289552558Sobrien declarations, file-scope (extern) function declarations (which 289652558Sobrien had no corresponding body) and file-scope tagged type declarations 289752558Sobrien and definitions which have not yet been forced out. */ 289852558Sobrien 289952558Sobrien if (write_symbols == DWARF2_DEBUG 290052558Sobrien && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl))) 290152558Sobrien TIMEVAR (symout_time, dwarf2out_decl (decl)); 290252558Sobrien#endif 290352558Sobrien } 290452558Sobrien} 290552558Sobrien 290618334Speter/* Compile an entire file of output from cpp, named NAME. 290718334Speter Write a file of assembly output and various debugging dumps. */ 290818334Speter 290918334Speterstatic void 291018334Spetercompile_file (name) 291118334Speter char *name; 291218334Speter{ 291318334Speter tree globals; 291418334Speter int start_time; 291518334Speter 291618334Speter int name_specified = name != 0; 291718334Speter 291818334Speter if (dump_base_name == 0) 291918334Speter dump_base_name = name ? name : "gccdump"; 292018334Speter 292118334Speter parse_time = 0; 292218334Speter varconst_time = 0; 292318334Speter integration_time = 0; 292418334Speter jump_time = 0; 292518334Speter cse_time = 0; 292650615Sobrien gcse_time = 0; 292718334Speter loop_time = 0; 292818334Speter cse2_time = 0; 292950615Sobrien branch_prob_time = 0; 293018334Speter flow_time = 0; 293118334Speter combine_time = 0; 293250615Sobrien regmove_time = 0; 293318334Speter sched_time = 0; 293418334Speter local_alloc_time = 0; 293518334Speter global_alloc_time = 0; 293652558Sobrien flow2_time = 0; 293718334Speter sched2_time = 0; 293850615Sobrien#ifdef DELAY_SLOTS 293918334Speter dbr_sched_time = 0; 294050615Sobrien#endif 294118334Speter shorten_branch_time = 0; 294218334Speter stack_reg_time = 0; 294318334Speter final_time = 0; 294418334Speter symout_time = 0; 294518334Speter dump_time = 0; 294618334Speter 294718334Speter /* Initialize data in various passes. */ 294818334Speter 294918334Speter init_obstacks (); 295018334Speter init_tree_codes (); 295150615Sobrien name = init_parse (name); 295218334Speter init_rtl (); 295318334Speter init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL 295450615Sobrien || debug_info_level == DINFO_LEVEL_VERBOSE 295550615Sobrien || flag_test_coverage); 295618334Speter init_regs (); 295718334Speter init_decl_processing (); 295818334Speter init_optabs (); 295918334Speter init_stmt (); 296018334Speter init_expmed (); 296118334Speter init_expr_once (); 296218334Speter init_loop (); 296318334Speter init_reload (); 296450615Sobrien init_alias_once (); 296518334Speter 296618334Speter if (flag_caller_saves) 296718334Speter init_caller_save (); 296818334Speter 296918334Speter /* If auxiliary info generation is desired, open the output file. 297018334Speter This goes in the same directory as the source file--unlike 297118334Speter all the other output files. */ 297218334Speter if (flag_gen_aux_info) 297318334Speter { 297418334Speter aux_info_file = fopen (aux_info_file_name, "w"); 297518334Speter if (aux_info_file == 0) 297618334Speter pfatal_with_name (aux_info_file_name); 297718334Speter } 297818334Speter 297952558Sobrien /* Clear the dump files. */ 298018334Speter if (rtl_dump) 298150615Sobrien clean_dump_file (".rtl"); 298218334Speter if (jump_opt_dump) 298352558Sobrien { 298452558Sobrien clean_dump_file (".jump"); 298552558Sobrien if (graph_dump_format != no_graph) 298652558Sobrien clean_graph_dump_file (dump_base_name, ".jump"); 298752558Sobrien } 298850615Sobrien if (addressof_dump) 298952558Sobrien { 299052558Sobrien clean_dump_file (".addressof"); 299152558Sobrien if (graph_dump_format != no_graph) 299252558Sobrien clean_graph_dump_file (dump_base_name, ".addressof"); 299352558Sobrien } 299418334Speter if (cse_dump) 299552558Sobrien { 299652558Sobrien clean_dump_file (".cse"); 299752558Sobrien if (graph_dump_format != no_graph) 299852558Sobrien clean_graph_dump_file (dump_base_name, ".cse"); 299952558Sobrien } 300018334Speter if (loop_dump) 300152558Sobrien { 300252558Sobrien clean_dump_file (".loop"); 300352558Sobrien if (graph_dump_format != no_graph) 300452558Sobrien clean_graph_dump_file (dump_base_name, ".loop"); 300552558Sobrien } 300618334Speter if (cse2_dump) 300752558Sobrien { 300852558Sobrien clean_dump_file (".cse2"); 300952558Sobrien if (graph_dump_format != no_graph) 301052558Sobrien clean_graph_dump_file (dump_base_name, ".cse2"); 301152558Sobrien } 301250615Sobrien if (branch_prob_dump) 301352558Sobrien { 301452558Sobrien clean_dump_file (".bp"); 301552558Sobrien if (graph_dump_format != no_graph) 301652558Sobrien clean_graph_dump_file (dump_base_name, ".bp"); 301752558Sobrien } 301818334Speter if (flow_dump) 301952558Sobrien { 302052558Sobrien clean_dump_file (".flow"); 302152558Sobrien if (graph_dump_format != no_graph) 302252558Sobrien clean_graph_dump_file (dump_base_name, ".flow"); 302352558Sobrien } 302418334Speter if (combine_dump) 302552558Sobrien { 302652558Sobrien clean_dump_file (".combine"); 302752558Sobrien if (graph_dump_format != no_graph) 302852558Sobrien clean_graph_dump_file (dump_base_name, ".combine"); 302952558Sobrien } 303050615Sobrien if (regmove_dump) 303152558Sobrien { 303252558Sobrien clean_dump_file (".regmove"); 303352558Sobrien if (graph_dump_format != no_graph) 303452558Sobrien clean_graph_dump_file (dump_base_name, ".regmove"); 303552558Sobrien } 303618334Speter if (sched_dump) 303752558Sobrien { 303852558Sobrien clean_dump_file (".sched"); 303952558Sobrien if (graph_dump_format != no_graph) 304052558Sobrien clean_graph_dump_file (dump_base_name, ".sched"); 304152558Sobrien } 304218334Speter if (local_reg_dump) 304352558Sobrien { 304452558Sobrien clean_dump_file (".lreg"); 304552558Sobrien if (graph_dump_format != no_graph) 304652558Sobrien clean_graph_dump_file (dump_base_name, ".lreg"); 304752558Sobrien } 304818334Speter if (global_reg_dump) 304952558Sobrien { 305052558Sobrien clean_dump_file (".greg"); 305152558Sobrien if (graph_dump_format != no_graph) 305252558Sobrien clean_graph_dump_file (dump_base_name, ".greg"); 305352558Sobrien } 305452558Sobrien if (flow2_dump) 305552558Sobrien { 305652558Sobrien clean_dump_file (".flow2"); 305752558Sobrien if (graph_dump_format != no_graph) 305852558Sobrien clean_graph_dump_file (dump_base_name, ".flow2"); 305952558Sobrien } 306018334Speter if (sched2_dump) 306152558Sobrien { 306252558Sobrien clean_dump_file (".sched2"); 306352558Sobrien if (graph_dump_format != no_graph) 306452558Sobrien clean_graph_dump_file (dump_base_name, ".sched2"); 306552558Sobrien } 306618334Speter if (jump2_opt_dump) 306752558Sobrien { 306852558Sobrien clean_dump_file (".jump2"); 306952558Sobrien if (graph_dump_format != no_graph) 307052558Sobrien clean_graph_dump_file (dump_base_name, ".jump2"); 307152558Sobrien } 307250615Sobrien#ifdef DELAY_SLOTS 307318334Speter if (dbr_sched_dump) 307452558Sobrien { 307552558Sobrien clean_dump_file (".dbr"); 307652558Sobrien if (graph_dump_format != no_graph) 307752558Sobrien clean_graph_dump_file (dump_base_name, ".dbr"); 307852558Sobrien } 307950615Sobrien#endif 308050615Sobrien if (gcse_dump) 308152558Sobrien { 308252558Sobrien clean_dump_file (".gcse"); 308352558Sobrien if (graph_dump_format != no_graph) 308452558Sobrien clean_graph_dump_file (dump_base_name, ".gcse"); 308552558Sobrien } 308618334Speter#ifdef STACK_REGS 308718334Speter if (stack_reg_dump) 308852558Sobrien { 308952558Sobrien clean_dump_file (".stack"); 309052558Sobrien if (graph_dump_format != no_graph) 309152558Sobrien clean_graph_dump_file (dump_base_name, ".stack"); 309252558Sobrien } 309318334Speter#endif 309450615Sobrien#ifdef MACHINE_DEPENDENT_REORG 309550615Sobrien if (mach_dep_reorg_dump) 309652558Sobrien { 309752558Sobrien clean_dump_file (".mach"); 309852558Sobrien if (graph_dump_format != no_graph) 309952558Sobrien clean_graph_dump_file (dump_base_name, ".mach"); 310052558Sobrien } 310150615Sobrien#endif 310218334Speter 310318334Speter /* Open assembler code output file. */ 310418334Speter 310552558Sobrien if (flag_syntax_only) 310652558Sobrien asm_out_file = NULL; 310718334Speter else 310818334Speter { 310952558Sobrien if (! name_specified && asm_file_name == 0) 311052558Sobrien asm_out_file = stdout; 311152558Sobrien else 311218334Speter { 311352558Sobrien int len = strlen (dump_base_name); 311452558Sobrien register char *dumpname = (char *) xmalloc (len + 6); 311552558Sobrien strcpy (dumpname, dump_base_name); 311652558Sobrien strip_off_ending (dumpname, len); 311752558Sobrien strcat (dumpname, ".s"); 311852558Sobrien if (asm_file_name == 0) 311952558Sobrien { 312052558Sobrien asm_file_name = (char *) xmalloc (strlen (dumpname) + 1); 312152558Sobrien strcpy (asm_file_name, dumpname); 312252558Sobrien } 312352558Sobrien if (!strcmp (asm_file_name, "-")) 312452558Sobrien asm_out_file = stdout; 312552558Sobrien else 312652558Sobrien asm_out_file = fopen (asm_file_name, "w"); 312752558Sobrien if (asm_out_file == 0) 312852558Sobrien pfatal_with_name (asm_file_name); 312918334Speter } 313018334Speter 313118334Speter#ifdef IO_BUFFER_SIZE 313252558Sobrien setvbuf (asm_out_file, (char *) xmalloc (IO_BUFFER_SIZE), 313352558Sobrien _IOFBF, IO_BUFFER_SIZE); 313418334Speter#endif 313552558Sobrien } 313618334Speter 313718334Speter input_filename = name; 313818334Speter 313918334Speter /* Put an entry on the input file stack for the main input file. */ 314018334Speter input_file_stack 314118334Speter = (struct file_stack *) xmalloc (sizeof (struct file_stack)); 314218334Speter input_file_stack->next = 0; 314318334Speter input_file_stack->name = input_filename; 314418334Speter 314518334Speter /* Perform language-specific initialization. 314618334Speter This may set main_input_filename. */ 314718334Speter lang_init (); 314818334Speter 314918334Speter /* If the input doesn't start with a #line, use the input name 315018334Speter as the official input file name. */ 315118334Speter if (main_input_filename == 0) 315218334Speter main_input_filename = name; 315318334Speter 315452558Sobrien if (flag_syntax_only) 315552558Sobrien { 315652558Sobrien write_symbols = NO_DEBUG; 315752558Sobrien profile_flag = 0; 315852558Sobrien profile_block_flag = 0; 315952558Sobrien } 316052558Sobrien else 316152558Sobrien { 316252558Sobrien ASM_FILE_START (asm_out_file); 316350615Sobrien 316450615Sobrien#ifdef ASM_COMMENT_START 316552558Sobrien if (flag_verbose_asm) 316652558Sobrien { 316752558Sobrien /* Print the list of options in effect. */ 316852558Sobrien print_version (asm_out_file, ASM_COMMENT_START); 316952558Sobrien print_switch_values (asm_out_file, 0, MAX_LINE, 317050615Sobrien ASM_COMMENT_START, " ", "\n"); 317152558Sobrien /* Add a blank line here so it appears in assembler output but not 317252558Sobrien screen output. */ 317352558Sobrien fprintf (asm_out_file, "\n"); 317452558Sobrien } 317550615Sobrien#endif 317618334Speter 317752558Sobrien /* Output something to inform GDB that this compilation was by GCC. */ 317818334Speter#ifndef ASM_IDENTIFY_GCC 317952558Sobrien fprintf (asm_out_file, "gcc2_compiled.:\n"); 318018334Speter#else 318152558Sobrien ASM_IDENTIFY_GCC (asm_out_file); 318218334Speter#endif 318318334Speter 318450615Sobrien /* Output something to identify which front-end produced this file. */ 318518334Speter#ifdef ASM_IDENTIFY_LANGUAGE 318652558Sobrien ASM_IDENTIFY_LANGUAGE (asm_out_file); 318718334Speter#endif 318852558Sobrien } /* ! flag_syntax_only */ 318918334Speter 319050615Sobrien#ifndef ASM_OUTPUT_SECTION_NAME 319150615Sobrien if (flag_function_sections) 319218334Speter { 319350615Sobrien warning ("-ffunction-sections not supported for this target."); 319450615Sobrien flag_function_sections = 0; 319518334Speter } 319652558Sobrien if (flag_data_sections) 319752558Sobrien { 319852558Sobrien warning ("-fdata-sections not supported for this target."); 319952558Sobrien flag_data_sections = 0; 320052558Sobrien } 320150615Sobrien#endif 320250615Sobrien 320350615Sobrien if (flag_function_sections 320450615Sobrien && (profile_flag || profile_block_flag)) 320518334Speter { 320650615Sobrien warning ("-ffunction-sections disabled; it makes profiling impossible."); 320750615Sobrien flag_function_sections = 0; 320850615Sobrien } 320950615Sobrien 321052558Sobrien#ifndef OBJECT_FORMAT_ELF 321150615Sobrien if (flag_function_sections && write_symbols != NO_DEBUG) 321250615Sobrien warning ("-ffunction-sections may affect debugging on some targets."); 321352558Sobrien#endif 321450615Sobrien 321550615Sobrien /* ??? Note: There used to be a conditional here 321650615Sobrien to call assemble_zeros without fail if DBX_DEBUGGING_INFO is defined. 321750615Sobrien This was to guarantee separation between gcc_compiled. and 321850615Sobrien the first function, for the sake of dbx on Suns. 321950615Sobrien However, having the extra zero here confused the Emacs 322050615Sobrien code for unexec, and might confuse other programs too. 322150615Sobrien Therefore, I took out that change. 322250615Sobrien In future versions we should find another way to solve 322350615Sobrien that dbx problem. -- rms, 23 May 93. */ 322418334Speter 322550615Sobrien /* Don't let the first function fall at the same address 322650615Sobrien as gcc_compiled., if profiling. */ 322750615Sobrien if (profile_flag || profile_block_flag) 322850615Sobrien { 322950615Sobrien /* It's best if we can write a nop here since some 323050615Sobrien assemblers don't tolerate zeros in the text section. */ 323150615Sobrien if (insn_template[CODE_FOR_nop] != 0) 323250615Sobrien output_asm_insn (insn_template[CODE_FOR_nop], NULL_PTR); 323350615Sobrien else 323418334Speter assemble_zeros (UNITS_PER_WORD); 323518334Speter } 323618334Speter 323718334Speter /* If dbx symbol table desired, initialize writing it 323818334Speter and output the predefined types. */ 323918334Speter#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) 324018334Speter if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) 324118334Speter TIMEVAR (symout_time, dbxout_init (asm_out_file, main_input_filename, 324218334Speter getdecls ())); 324318334Speter#endif 324418334Speter#ifdef SDB_DEBUGGING_INFO 324518334Speter if (write_symbols == SDB_DEBUG) 324618334Speter TIMEVAR (symout_time, sdbout_init (asm_out_file, main_input_filename, 324718334Speter getdecls ())); 324818334Speter#endif 324918334Speter#ifdef DWARF_DEBUGGING_INFO 325018334Speter if (write_symbols == DWARF_DEBUG) 325118334Speter TIMEVAR (symout_time, dwarfout_init (asm_out_file, main_input_filename)); 325218334Speter#endif 325350615Sobrien#ifdef DWARF2_UNWIND_INFO 325450615Sobrien if (dwarf2out_do_frame ()) 325550615Sobrien dwarf2out_frame_init (); 325650615Sobrien#endif 325750615Sobrien#ifdef DWARF2_DEBUGGING_INFO 325850615Sobrien if (write_symbols == DWARF2_DEBUG) 325950615Sobrien TIMEVAR (symout_time, dwarf2out_init (asm_out_file, main_input_filename)); 326050615Sobrien#endif 326118334Speter 326218334Speter /* Initialize yet another pass. */ 326318334Speter 326450615Sobrien init_final (main_input_filename); 326550615Sobrien init_branch_prob (dump_base_name); 326618334Speter 326718334Speter start_time = get_run_time (); 326818334Speter 326918334Speter /* Call the parser, which parses the entire file 327018334Speter (calling rest_of_compilation for each function). */ 327118334Speter 327218334Speter if (yyparse () != 0) 327318334Speter { 327418334Speter if (errorcount == 0) 327552558Sobrien notice ("Errors detected in input file (your bison.simple is out of date)\n"); 327618334Speter 327718334Speter /* In case there were missing closebraces, 327818334Speter get us back to the global binding level. */ 327918334Speter while (! global_bindings_p ()) 328018334Speter poplevel (0, 0, 0); 328118334Speter } 328218334Speter 328318334Speter /* Compilation is now finished except for writing 328418334Speter what's left of the symbol table output. */ 328518334Speter 328618334Speter parse_time += get_run_time () - start_time; 328718334Speter 328818334Speter parse_time -= integration_time; 328918334Speter parse_time -= varconst_time; 329018334Speter 329152558Sobrien if (flag_syntax_only) 329252558Sobrien goto finish_syntax; 329352558Sobrien 329418334Speter globals = getdecls (); 329518334Speter 329618334Speter /* Really define vars that have had only a tentative definition. 329718334Speter Really output inline functions that must actually be callable 329818334Speter and have not been output so far. */ 329918334Speter 330018334Speter { 330118334Speter int len = list_length (globals); 330218334Speter tree *vec = (tree *) alloca (sizeof (tree) * len); 330318334Speter int i; 330418334Speter tree decl; 330518334Speter 330618334Speter /* Process the decls in reverse order--earliest first. 330718334Speter Put them into VEC from back to front, then take out from front. */ 330818334Speter 330918334Speter for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl)) 331018334Speter vec[len - i - 1] = decl; 331118334Speter 331252558Sobrien wrapup_global_declarations (vec, len); 331318334Speter 331452558Sobrien /* This must occur after the loop to output deferred functions. Else 331552558Sobrien the profiler initializer would not be emitted if all the functions 331652558Sobrien in this compilation unit were deferred. 331718334Speter 331852558Sobrien output_func_start_profiler can not cause any additional functions or 331952558Sobrien data to need to be output, so it need not be in the deferred function 332052558Sobrien loop above. */ 332152558Sobrien output_func_start_profiler (); 332218334Speter 332350615Sobrien /* Now that all possible functions have been output, we can dump 332450615Sobrien the exception table. */ 332550615Sobrien 332650615Sobrien output_exception_table (); 332750615Sobrien 332852558Sobrien check_global_declarations (vec, len); 332918334Speter } 333018334Speter 333118334Speter /* Write out any pending weak symbol declarations. */ 333218334Speter 333318334Speter weak_finish (); 333418334Speter 333518334Speter /* Do dbx symbols */ 333618334Speter#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) 333718334Speter if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) 333818334Speter TIMEVAR (symout_time, 333918334Speter { 334018334Speter dbxout_finish (asm_out_file, main_input_filename); 334118334Speter }); 334218334Speter#endif 334318334Speter 334418334Speter#ifdef DWARF_DEBUGGING_INFO 334518334Speter if (write_symbols == DWARF_DEBUG) 334618334Speter TIMEVAR (symout_time, 334718334Speter { 334818334Speter dwarfout_finish (); 334918334Speter }); 335018334Speter#endif 335118334Speter 335250615Sobrien#ifdef DWARF2_UNWIND_INFO 335350615Sobrien if (dwarf2out_do_frame ()) 335450615Sobrien dwarf2out_frame_finish (); 335550615Sobrien#endif 335650615Sobrien 335750615Sobrien#ifdef DWARF2_DEBUGGING_INFO 335850615Sobrien if (write_symbols == DWARF2_DEBUG) 335950615Sobrien TIMEVAR (symout_time, 336050615Sobrien { 336150615Sobrien dwarf2out_finish (); 336250615Sobrien }); 336350615Sobrien#endif 336450615Sobrien 336518334Speter /* Output some stuff at end of file if nec. */ 336618334Speter 336750615Sobrien end_final (dump_base_name); 336850615Sobrien 336950615Sobrien if (branch_prob_dump) 337050615Sobrien open_dump_file (".bp", NULL); 337150615Sobrien 337250615Sobrien TIMEVAR (dump_time, end_branch_prob (rtl_dump_file)); 337350615Sobrien 337450615Sobrien if (branch_prob_dump) 337550615Sobrien close_dump_file (NULL, NULL_RTX); 337650615Sobrien 337718334Speter#ifdef ASM_FILE_END 337850615Sobrien ASM_FILE_END (asm_out_file); 337918334Speter#endif 338018334Speter 338152558Sobrien 338218334Speter /* Language-specific end of compilation actions. */ 338352558Sobrien finish_syntax: 338418334Speter lang_finish (); 338518334Speter 338618334Speter /* Close the dump files. */ 338718334Speter 338818334Speter if (flag_gen_aux_info) 338918334Speter { 339018334Speter fclose (aux_info_file); 339118334Speter if (errorcount) 339218334Speter unlink (aux_info_file_name); 339318334Speter } 339418334Speter 339518334Speter if (combine_dump) 339618334Speter { 339750615Sobrien open_dump_file (".combine", NULL); 339850615Sobrien TIMEVAR (dump_time, dump_combine_total_stats (rtl_dump_file)); 339950615Sobrien close_dump_file (NULL, NULL_RTX); 340018334Speter } 340118334Speter 340218334Speter /* Close non-debugging input and output files. Take special care to note 340318334Speter whether fclose returns an error, since the pages might still be on the 340418334Speter buffer chain while the file is open. */ 340518334Speter 340650615Sobrien finish_parse (); 340750615Sobrien 340852558Sobrien if (! flag_syntax_only 340952558Sobrien && (ferror (asm_out_file) != 0 || fclose (asm_out_file) != 0)) 341018334Speter fatal_io_error (asm_file_name); 341118334Speter 341252558Sobrien /* Do whatever is necessary to finish printing the graphs. */ 341352558Sobrien if (graph_dump_format != no_graph) 341452558Sobrien { 341552558Sobrien if (jump_opt_dump) 341652558Sobrien finish_graph_dump_file (dump_base_name, ".jump"); 341752558Sobrien if (addressof_dump) 341852558Sobrien finish_graph_dump_file (dump_base_name, ".addressof"); 341952558Sobrien if (cse_dump) 342052558Sobrien finish_graph_dump_file (dump_base_name, ".cse"); 342152558Sobrien if (loop_dump) 342252558Sobrien finish_graph_dump_file (dump_base_name, ".loop"); 342352558Sobrien if (cse2_dump) 342452558Sobrien finish_graph_dump_file (dump_base_name, ".cse2"); 342552558Sobrien if (branch_prob_dump) 342652558Sobrien finish_graph_dump_file (dump_base_name, ".bp"); 342752558Sobrien if (flow_dump) 342852558Sobrien finish_graph_dump_file (dump_base_name, ".flow"); 342952558Sobrien if (combine_dump) 343052558Sobrien finish_graph_dump_file (dump_base_name, ".combine"); 343152558Sobrien if (regmove_dump) 343252558Sobrien finish_graph_dump_file (dump_base_name, ".regmove"); 343352558Sobrien if (sched_dump) 343452558Sobrien finish_graph_dump_file (dump_base_name, ".sched"); 343552558Sobrien if (local_reg_dump) 343652558Sobrien finish_graph_dump_file (dump_base_name, ".lreg"); 343752558Sobrien if (global_reg_dump) 343852558Sobrien finish_graph_dump_file (dump_base_name, ".greg"); 343952558Sobrien if (flow2_dump) 344052558Sobrien finish_graph_dump_file (dump_base_name, ".flow2"); 344152558Sobrien if (sched2_dump) 344252558Sobrien finish_graph_dump_file (dump_base_name, ".sched2"); 344352558Sobrien if (jump2_opt_dump) 344452558Sobrien finish_graph_dump_file (dump_base_name, ".jump2"); 344552558Sobrien#ifdef DELAY_SLOTS 344652558Sobrien if (dbr_sched_dump) 344752558Sobrien finish_graph_dump_file (dump_base_name, ".dbr"); 344852558Sobrien#endif 344952558Sobrien if (gcse_dump) 345052558Sobrien finish_graph_dump_file (dump_base_name, ".gcse"); 345152558Sobrien#ifdef STACK_REGS 345252558Sobrien if (stack_reg_dump) 345352558Sobrien finish_graph_dump_file (dump_base_name, ".stack"); 345452558Sobrien#endif 345552558Sobrien#ifdef MACHINE_DEPENDENT_REORG 345652558Sobrien if (mach_dep_reorg_dump) 345752558Sobrien finish_graph_dump_file (dump_base_name, ".mach"); 345852558Sobrien#endif 345952558Sobrien } 346052558Sobrien 346152558Sobrien /* Free up memory for the benefit of leak detectors. */ 346252558Sobrien free_reg_info (); 346352558Sobrien 346418334Speter /* Print the times. */ 346518334Speter 346618334Speter if (! quiet_flag) 346718334Speter { 346818334Speter fprintf (stderr,"\n"); 346918334Speter print_time ("parse", parse_time); 347018334Speter 347150615Sobrien print_time ("integration", integration_time); 347250615Sobrien print_time ("jump", jump_time); 347350615Sobrien print_time ("cse", cse_time); 347450615Sobrien print_time ("gcse", gcse_time); 347550615Sobrien print_time ("loop", loop_time); 347650615Sobrien print_time ("cse2", cse2_time); 347750615Sobrien print_time ("branch-prob", branch_prob_time); 347850615Sobrien print_time ("flow", flow_time); 347950615Sobrien print_time ("combine", combine_time); 348050615Sobrien print_time ("regmove", regmove_time); 348150615Sobrien print_time ("sched", sched_time); 348250615Sobrien print_time ("local-alloc", local_alloc_time); 348350615Sobrien print_time ("global-alloc", global_alloc_time); 348452558Sobrien print_time ("flow2", flow2_time); 348550615Sobrien print_time ("sched2", sched2_time); 348650615Sobrien#ifdef DELAY_SLOTS 348750615Sobrien print_time ("dbranch", dbr_sched_time); 348850615Sobrien#endif 348950615Sobrien print_time ("shorten-branch", shorten_branch_time); 349050615Sobrien print_time ("stack-reg", stack_reg_time); 349150615Sobrien print_time ("final", final_time); 349250615Sobrien print_time ("varconst", varconst_time); 349350615Sobrien print_time ("symout", symout_time); 349450615Sobrien print_time ("dump", dump_time); 349518334Speter } 349618334Speter} 349718334Speter 349818334Speter/* This is called from various places for FUNCTION_DECL, VAR_DECL, 349918334Speter and TYPE_DECL nodes. 350018334Speter 350118334Speter This does nothing for local (non-static) variables. 350218334Speter Otherwise, it sets up the RTL and outputs any assembler code 350318334Speter (label definition, storage allocation and initialization). 350418334Speter 350518334Speter DECL is the declaration. If ASMSPEC is nonzero, it specifies 350618334Speter the assembler symbol name to be used. TOP_LEVEL is nonzero 350718334Speter if this declaration is not within a function. */ 350818334Speter 350918334Spetervoid 351018334Speterrest_of_decl_compilation (decl, asmspec, top_level, at_end) 351118334Speter tree decl; 351252558Sobrien const char *asmspec; 351318334Speter int top_level; 351418334Speter int at_end; 351518334Speter{ 351618334Speter /* Declarations of variables, and of functions defined elsewhere. */ 351718334Speter 351818334Speter/* The most obvious approach, to put an #ifndef around where 351918334Speter this macro is used, doesn't work since it's inside a macro call. */ 352018334Speter#ifndef ASM_FINISH_DECLARE_OBJECT 352118334Speter#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP, END) 352218334Speter#endif 352318334Speter 352418334Speter /* Forward declarations for nested functions are not "external", 352518334Speter but we need to treat them as if they were. */ 352618334Speter if (TREE_STATIC (decl) || DECL_EXTERNAL (decl) 352718334Speter || TREE_CODE (decl) == FUNCTION_DECL) 352818334Speter TIMEVAR (varconst_time, 352918334Speter { 353018334Speter make_decl_rtl (decl, asmspec, top_level); 353118334Speter /* Initialized extern variable exists to be replaced 353218334Speter with its value, or represents something that will be 353318334Speter output in another file. */ 353418334Speter if (! (TREE_CODE (decl) == VAR_DECL 353518334Speter && DECL_EXTERNAL (decl) && TREE_READONLY (decl) 353618334Speter && DECL_INITIAL (decl) != 0 353718334Speter && DECL_INITIAL (decl) != error_mark_node)) 353818334Speter /* Don't output anything 353918334Speter when a tentative file-scope definition is seen. 354018334Speter But at end of compilation, do output code for them. */ 354118334Speter if (! (! at_end && top_level 354218334Speter && (DECL_INITIAL (decl) == 0 354318334Speter || DECL_INITIAL (decl) == error_mark_node))) 354418334Speter assemble_variable (decl, top_level, at_end, 0); 354518334Speter if (decl == last_assemble_variable_decl) 354618334Speter { 354718334Speter ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl, 354818334Speter top_level, at_end); 354918334Speter } 355018334Speter }); 355118334Speter else if (DECL_REGISTER (decl) && asmspec != 0) 355218334Speter { 355318334Speter if (decode_reg_name (asmspec) >= 0) 355418334Speter { 355518334Speter DECL_RTL (decl) = 0; 355618334Speter make_decl_rtl (decl, asmspec, top_level); 355718334Speter } 355818334Speter else 355918334Speter error ("invalid register name `%s' for register variable", asmspec); 356018334Speter } 356118334Speter#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) 356218334Speter else if ((write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) 356318334Speter && TREE_CODE (decl) == TYPE_DECL) 356418334Speter TIMEVAR (symout_time, dbxout_symbol (decl, 0)); 356518334Speter#endif 356618334Speter#ifdef SDB_DEBUGGING_INFO 356718334Speter else if (write_symbols == SDB_DEBUG && top_level 356818334Speter && TREE_CODE (decl) == TYPE_DECL) 356918334Speter TIMEVAR (symout_time, sdbout_symbol (decl, 0)); 357018334Speter#endif 357118334Speter} 357218334Speter 357318334Speter/* Called after finishing a record, union or enumeral type. */ 357418334Speter 357518334Spetervoid 357618334Speterrest_of_type_compilation (type, toplev) 357752558Sobrien#if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO) || defined (SDB_DEBUGGING_INFO) 357818334Speter tree type; 357918334Speter int toplev; 358052558Sobrien#else 358152558Sobrien tree type ATTRIBUTE_UNUSED; 358252558Sobrien int toplev ATTRIBUTE_UNUSED; 358352558Sobrien#endif 358418334Speter{ 358518334Speter#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) 358618334Speter if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) 358718334Speter TIMEVAR (symout_time, dbxout_symbol (TYPE_STUB_DECL (type), !toplev)); 358818334Speter#endif 358918334Speter#ifdef SDB_DEBUGGING_INFO 359018334Speter if (write_symbols == SDB_DEBUG) 359118334Speter TIMEVAR (symout_time, sdbout_symbol (TYPE_STUB_DECL (type), !toplev)); 359218334Speter#endif 359318334Speter} 359418334Speter 359518334Speter/* This is called from finish_function (within yyparse) 359618334Speter after each top-level definition is parsed. 359718334Speter It is supposed to compile that function or variable 359818334Speter and output the assembler code for it. 359918334Speter After we return, the tree storage is freed. */ 360018334Speter 360118334Spetervoid 360218334Speterrest_of_compilation (decl) 360318334Speter tree decl; 360418334Speter{ 360518334Speter register rtx insns; 360618334Speter int start_time = get_run_time (); 360718334Speter int tem; 360818334Speter /* Nonzero if we have saved the original DECL_INITIAL of the function, 360918334Speter to be restored after we finish compiling the function 361018334Speter (for use when compiling inline calls to this function). */ 361118334Speter tree saved_block_tree = 0; 361218334Speter /* Likewise, for DECL_ARGUMENTS. */ 361318334Speter tree saved_arguments = 0; 361418334Speter int failure = 0; 361552558Sobrien int rebuild_label_notes_after_reload; 361618334Speter 361718334Speter /* If we are reconsidering an inline function 361818334Speter at the end of compilation, skip the stuff for making it inline. */ 361918334Speter 362018334Speter if (DECL_SAVED_INSNS (decl) == 0) 362118334Speter { 362250615Sobrien int inlinable = 0; 362352558Sobrien const char *lose; 362418334Speter 362518334Speter /* If requested, consider whether to make this function inline. */ 362650615Sobrien if (DECL_INLINE (decl) || flag_inline_functions) 362718334Speter TIMEVAR (integration_time, 362818334Speter { 362918334Speter lose = function_cannot_inline_p (decl); 363018334Speter if (lose || ! optimize) 363118334Speter { 363250615Sobrien if (warn_inline && DECL_INLINE (decl)) 363318334Speter warning_with_decl (decl, lose); 363418334Speter DECL_ABSTRACT_ORIGIN (decl) = 0; 363518334Speter /* Don't really compile an extern inline function. 363618334Speter If we can't make it inline, pretend 363718334Speter it was only declared. */ 363818334Speter if (DECL_EXTERNAL (decl)) 363918334Speter { 364018334Speter DECL_INITIAL (decl) = 0; 364118334Speter goto exit_rest_of_compilation; 364218334Speter } 364318334Speter } 364418334Speter else 364550615Sobrien /* ??? Note that this has the effect of making it look 364650615Sobrien like "inline" was specified for a function if we choose 364750615Sobrien to inline it. This isn't quite right, but it's 364850615Sobrien probably not worth the trouble to fix. */ 364950615Sobrien inlinable = DECL_INLINE (decl) = 1; 365018334Speter }); 365118334Speter 365218334Speter insns = get_insns (); 365318334Speter 365418334Speter /* Dump the rtl code if we are dumping rtl. */ 365518334Speter 365618334Speter if (rtl_dump) 365750615Sobrien { 365850615Sobrien open_dump_file (".rtl", decl_printable_name (decl, 2)); 365950615Sobrien 366050615Sobrien if (DECL_SAVED_INSNS (decl)) 366150615Sobrien fprintf (rtl_dump_file, ";; (integrable)\n\n"); 366250615Sobrien 366350615Sobrien close_dump_file (print_rtl, insns); 366450615Sobrien } 366518334Speter 366650615Sobrien /* If we can, defer compiling inlines until EOF. 366750615Sobrien save_for_inline_copying can be extremely expensive. */ 366850615Sobrien if (inlinable && ! decl_function_context (decl)) 366950615Sobrien DECL_DEFER_OUTPUT (decl) = 1; 367050615Sobrien 367118334Speter /* If function is inline, and we don't yet know whether to 367218334Speter compile it by itself, defer decision till end of compilation. 367318334Speter finish_compilation will call rest_of_compilation again 367418334Speter for those functions that need to be output. Also defer those 367550615Sobrien functions that we are supposed to defer. We cannot defer 367650615Sobrien functions containing nested functions since the nested function 367750615Sobrien data is in our non-saved obstack. We cannot defer nested 367850615Sobrien functions for the same reason. */ 367918334Speter 368050615Sobrien /* If this is a nested inline, remove ADDRESSOF now so we can 368150615Sobrien finish compiling ourselves. Otherwise, wait until EOF. 368250615Sobrien We have to do this because the purge_addressof transformation 368350615Sobrien changes the DECL_RTL for many variables, which confuses integrate. */ 368450615Sobrien if (inlinable) 368518334Speter { 368650615Sobrien if (decl_function_context (decl)) 368750615Sobrien purge_addressof (insns); 368850615Sobrien else 368950615Sobrien DECL_DEFER_OUTPUT (decl) = 1; 369050615Sobrien } 369150615Sobrien 369250615Sobrien if (! current_function_contains_functions 369350615Sobrien && (DECL_DEFER_OUTPUT (decl) 369450615Sobrien || (DECL_INLINE (decl) 369550615Sobrien && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl) 369650615Sobrien && ! flag_keep_inline_functions) 369750615Sobrien || DECL_EXTERNAL (decl))))) 369850615Sobrien { 369918334Speter DECL_DEFER_OUTPUT (decl) = 1; 370018334Speter 370150615Sobrien /* If -Wreturn-type, we have to do a bit of compilation. 370250615Sobrien However, if we just fall through we will call 370350615Sobrien save_for_inline_copying() which results in excessive 370450615Sobrien memory use. Instead, we just want to call 370550615Sobrien jump_optimize() to figure out whether or not we can fall 370650615Sobrien off the end of the function; we do the minimum amount of 370750615Sobrien work necessary to make that safe. And, we set optimize 370850615Sobrien to zero to keep jump_optimize from working too hard. */ 370950615Sobrien if (warn_return_type) 371018334Speter { 371150615Sobrien int saved_optimize = optimize; 371250615Sobrien optimize = 0; 371350615Sobrien find_exception_handler_labels (); 371450615Sobrien jump_optimize (get_insns(), !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES, 371550615Sobrien !JUMP_AFTER_REGSCAN); 371650615Sobrien optimize = saved_optimize; 371750615Sobrien } 371850615Sobrien 371918334Speter#ifdef DWARF_DEBUGGING_INFO 372050615Sobrien /* Generate the DWARF info for the "abstract" instance 372150615Sobrien of a function which we may later generate inlined and/or 372250615Sobrien out-of-line instances of. */ 372350615Sobrien if (write_symbols == DWARF_DEBUG) 372450615Sobrien { 372550615Sobrien set_decl_abstract_flags (decl, 1); 372650615Sobrien TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 0)); 372750615Sobrien set_decl_abstract_flags (decl, 0); 372850615Sobrien } 372918334Speter#endif 373050615Sobrien#ifdef DWARF2_DEBUGGING_INFO 373150615Sobrien /* Generate the DWARF2 info for the "abstract" instance 373250615Sobrien of a function which we may later generate inlined and/or 373350615Sobrien out-of-line instances of. */ 373450615Sobrien if (write_symbols == DWARF2_DEBUG) 373550615Sobrien { 373650615Sobrien set_decl_abstract_flags (decl, 1); 373750615Sobrien TIMEVAR (symout_time, dwarf2out_decl (decl)); 373850615Sobrien set_decl_abstract_flags (decl, 0); 373918334Speter } 374050615Sobrien#endif 374150615Sobrien TIMEVAR (integration_time, save_for_inline_nocopy (decl)); 374250615Sobrien RTX_INTEGRATED_P (DECL_SAVED_INSNS (decl)) = inlinable; 374350615Sobrien goto exit_rest_of_compilation; 374418334Speter } 374518334Speter 374618334Speter /* If we have to compile the function now, save its rtl and subdecls 374718334Speter so that its compilation will not affect what others get. */ 374850615Sobrien if (inlinable || DECL_DEFER_OUTPUT (decl)) 374918334Speter { 375018334Speter#ifdef DWARF_DEBUGGING_INFO 375118334Speter /* Generate the DWARF info for the "abstract" instance of 375218334Speter a function which we will generate an out-of-line instance 375318334Speter of almost immediately (and which we may also later generate 375418334Speter various inlined instances of). */ 375518334Speter if (write_symbols == DWARF_DEBUG) 375618334Speter { 375718334Speter set_decl_abstract_flags (decl, 1); 375818334Speter TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 0)); 375918334Speter set_decl_abstract_flags (decl, 0); 376018334Speter } 376118334Speter#endif 376250615Sobrien#ifdef DWARF2_DEBUGGING_INFO 376350615Sobrien /* Generate the DWARF2 info for the "abstract" instance of 376450615Sobrien a function which we will generate an out-of-line instance 376550615Sobrien of almost immediately (and which we may also later generate 376650615Sobrien various inlined instances of). */ 376750615Sobrien if (write_symbols == DWARF2_DEBUG) 376850615Sobrien { 376950615Sobrien set_decl_abstract_flags (decl, 1); 377050615Sobrien TIMEVAR (symout_time, dwarf2out_decl (decl)); 377150615Sobrien set_decl_abstract_flags (decl, 0); 377250615Sobrien } 377350615Sobrien#endif 377418334Speter saved_block_tree = DECL_INITIAL (decl); 377518334Speter saved_arguments = DECL_ARGUMENTS (decl); 377618334Speter TIMEVAR (integration_time, save_for_inline_copying (decl)); 377750615Sobrien RTX_INTEGRATED_P (DECL_SAVED_INSNS (decl)) = inlinable; 377818334Speter } 377918334Speter 378018334Speter /* If specified extern inline but we aren't inlining it, we are 378152558Sobrien done. This goes for anything that gets here with DECL_EXTERNAL 378252558Sobrien set, not just things with DECL_INLINE. */ 378352558Sobrien if (DECL_EXTERNAL (decl)) 378418334Speter goto exit_rest_of_compilation; 378518334Speter } 378618334Speter 378718334Speter if (! DECL_DEFER_OUTPUT (decl)) 378818334Speter TREE_ASM_WRITTEN (decl) = 1; 378918334Speter 379018334Speter /* Now that integrate will no longer see our rtl, we need not distinguish 379118334Speter between the return value of this function and the return value of called 379218334Speter functions. */ 379318334Speter rtx_equal_function_value_matters = 0; 379418334Speter 379518334Speter /* Don't return yet if -Wreturn-type; we need to do jump_optimize. */ 379618334Speter if ((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type) 379718334Speter { 379818334Speter goto exit_rest_of_compilation; 379918334Speter } 380018334Speter 380150615Sobrien /* Emit code to get eh context, if needed. */ 380250615Sobrien emit_eh_context (); 380318334Speter 380418334Speter#ifdef FINALIZE_PIC 380518334Speter /* If we are doing position-independent code generation, now 380618334Speter is the time to output special prologues and epilogues. 380718334Speter We do not want to do this earlier, because it just clutters 380818334Speter up inline functions with meaningless insns. */ 380918334Speter if (flag_pic) 381018334Speter FINALIZE_PIC; 381118334Speter#endif 381218334Speter 381350615Sobrien /* From now on, allocate rtl in current_obstack, not in saveable_obstack. 381450615Sobrien Note that that may have been done above, in save_for_inline_copying. 381550615Sobrien The call to resume_temporary_allocation near the end of this function 381650615Sobrien goes back to the usual state of affairs. This must be done after 381750615Sobrien we've built up any unwinders for exception handling, and done 381850615Sobrien the FINALIZE_PIC work, if necessary. */ 381950615Sobrien 382050615Sobrien rtl_in_current_obstack (); 382150615Sobrien 382218334Speter insns = get_insns (); 382318334Speter 382418334Speter /* Copy any shared structure that should not be shared. */ 382518334Speter 382618334Speter unshare_all_rtl (insns); 382718334Speter 382850615Sobrien#ifdef SETJMP_VIA_SAVE_AREA 382950615Sobrien /* This must be performed before virutal register instantiation. */ 383050615Sobrien if (current_function_calls_alloca) 383150615Sobrien optimize_save_area_alloca (insns); 383250615Sobrien#endif 383350615Sobrien 383418334Speter /* Instantiate all virtual registers. */ 383518334Speter 383618334Speter instantiate_virtual_regs (current_function_decl, get_insns ()); 383718334Speter 383818334Speter /* See if we have allocated stack slots that are not directly addressable. 383918334Speter If so, scan all the insns and create explicit address computation 384018334Speter for all references to such slots. */ 384118334Speter/* fixup_stack_slots (); */ 384218334Speter 384350615Sobrien /* Find all the EH handlers. */ 384450615Sobrien find_exception_handler_labels (); 384518334Speter 384650615Sobrien /* Always do one jump optimization pass to ensure that JUMP_LABEL fields 384750615Sobrien are initialized and to compute whether control can drop off the end 384850615Sobrien of the function. */ 384950615Sobrien TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0)); 385050615Sobrien TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES, 385150615Sobrien JUMP_AFTER_REGSCAN)); 385218334Speter 385318334Speter /* Now is when we stop if -fsyntax-only and -Wreturn-type. */ 385418334Speter if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl)) 385518334Speter goto exit_rest_of_compilation; 385618334Speter 385718334Speter /* Dump rtl code after jump, if we are doing that. */ 385818334Speter 385950615Sobrien if (jump_opt_dump) 386050615Sobrien dump_rtl (".jump", decl, print_rtl, insns); 386118334Speter 386218334Speter /* Perform common subexpression elimination. 386318334Speter Nonzero value from `cse_main' means that jumps were simplified 386418334Speter and some code may now be unreachable, so do 386518334Speter jump optimization again. */ 386618334Speter 386718334Speter if (optimize > 0) 386818334Speter { 386950615Sobrien if (cse_dump) 387050615Sobrien open_dump_file (".cse", decl_printable_name (decl, 2)); 387150615Sobrien 387218334Speter TIMEVAR (cse_time, reg_scan (insns, max_reg_num (), 1)); 387318334Speter 387418334Speter if (flag_thread_jumps) 387518334Speter /* Hacks by tiemann & kenner. */ 387618334Speter TIMEVAR (jump_time, thread_jumps (insns, max_reg_num (), 1)); 387718334Speter 387818334Speter TIMEVAR (cse_time, tem = cse_main (insns, max_reg_num (), 387950615Sobrien 0, rtl_dump_file)); 388050615Sobrien TIMEVAR (cse_time, delete_trivially_dead_insns (insns, max_reg_num ())); 388118334Speter 388218334Speter if (tem || optimize > 1) 388350615Sobrien TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP, 388450615Sobrien !JUMP_NOOP_MOVES, 388550615Sobrien !JUMP_AFTER_REGSCAN)); 388650615Sobrien 388750615Sobrien /* Dump rtl code after cse, if we are doing that. */ 388852558Sobrien 388950615Sobrien if (cse_dump) 389052558Sobrien { 389152558Sobrien close_dump_file (print_rtl, insns); 389252558Sobrien if (graph_dump_format != no_graph) 389352558Sobrien print_rtl_graph_with_bb (dump_base_name, ".cse", insns); 389452558Sobrien } 389518334Speter } 389618334Speter 389750615Sobrien purge_addressof (insns); 389850615Sobrien reg_scan (insns, max_reg_num (), 1); 389918334Speter 390050615Sobrien if (addressof_dump) 390152558Sobrien { 390252558Sobrien dump_rtl (".addressof", decl, print_rtl, insns); 390352558Sobrien if (graph_dump_format != no_graph) 390452558Sobrien print_rtl_graph_with_bb (dump_base_name, ".addressof", insns); 390552558Sobrien } 390652558Sobrien 390750615Sobrien /* Perform global cse. */ 390818334Speter 390950615Sobrien if (optimize > 0 && flag_gcse) 391050615Sobrien { 391150615Sobrien if (gcse_dump) 391250615Sobrien open_dump_file (".gcse", IDENTIFIER_POINTER (DECL_NAME (decl))); 391318334Speter 391452558Sobrien TIMEVAR (gcse_time, tem = gcse_main (insns, rtl_dump_file)); 391552558Sobrien 391652558Sobrien /* If gcse altered any jumps, rerun jump optimizations to clean 391752558Sobrien things up. */ 391852558Sobrien if (tem) 391952558Sobrien { 392052558Sobrien TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP, 392152558Sobrien !JUMP_NOOP_MOVES, 392252558Sobrien !JUMP_AFTER_REGSCAN)); 392352558Sobrien } 392452558Sobrien 392550615Sobrien if (gcse_dump) 392652558Sobrien { 392752558Sobrien close_dump_file (print_rtl, insns); 392852558Sobrien if (graph_dump_format != no_graph) 392952558Sobrien print_rtl_graph_with_bb (dump_base_name, ".gcse", insns); 393052558Sobrien } 393150615Sobrien } 393218334Speter /* Move constant computations out of loops. */ 393318334Speter 393418334Speter if (optimize > 0) 393518334Speter { 393650615Sobrien if (loop_dump) 393750615Sobrien open_dump_file (".loop", decl_printable_name (decl, 2)); 393850615Sobrien 393950615Sobrien TIMEVAR 394050615Sobrien (loop_time, 394150615Sobrien { 394250615Sobrien if (flag_rerun_loop_opt) 394318334Speter { 394450615Sobrien /* We only want to perform unrolling once. */ 394550615Sobrien 394652558Sobrien loop_optimize (insns, rtl_dump_file, 0, 0); 394750615Sobrien 394850615Sobrien 394950615Sobrien /* The first call to loop_optimize makes some instructions 395050615Sobrien trivially dead. We delete those instructions now in the 395150615Sobrien hope that doing so will make the heuristics in loop work 395250615Sobrien better and possibly speed up compilation. */ 395350615Sobrien delete_trivially_dead_insns (insns, max_reg_num ()); 395418334Speter 395550615Sobrien /* The regscan pass is currently necessary as the alias 395650615Sobrien analysis code depends on this information. */ 395750615Sobrien reg_scan (insns, max_reg_num (), 1); 395850615Sobrien } 395952558Sobrien loop_optimize (insns, rtl_dump_file, flag_unroll_loops, 1); 396050615Sobrien }); 396152558Sobrien 396250615Sobrien /* Dump rtl code after loop opt, if we are doing that. */ 396352558Sobrien 396450615Sobrien if (loop_dump) 396552558Sobrien { 396652558Sobrien close_dump_file (print_rtl, insns); 396752558Sobrien if (graph_dump_format != no_graph) 396852558Sobrien print_rtl_graph_with_bb (dump_base_name, ".loop", insns); 396952558Sobrien } 397050615Sobrien } 397118334Speter 397250615Sobrien if (optimize > 0) 397318334Speter { 397450615Sobrien if (cse2_dump) 397550615Sobrien open_dump_file (".cse2", decl_printable_name (decl, 2)); 397652558Sobrien 397750615Sobrien if (flag_rerun_cse_after_loop) 397850615Sobrien { 397950615Sobrien /* Running another jump optimization pass before the second 398050615Sobrien cse pass sometimes simplifies the RTL enough to allow 398150615Sobrien the second CSE pass to do a better job. Jump_optimize can change 398250615Sobrien max_reg_num so we must rerun reg_scan afterwards. 398350615Sobrien ??? Rework to not call reg_scan so often. */ 398450615Sobrien TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0)); 398550615Sobrien TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP, 398650615Sobrien !JUMP_NOOP_MOVES, 398750615Sobrien JUMP_AFTER_REGSCAN)); 398850615Sobrien 398950615Sobrien TIMEVAR (cse2_time, reg_scan (insns, max_reg_num (), 0)); 399050615Sobrien TIMEVAR (cse2_time, tem = cse_main (insns, max_reg_num (), 399150615Sobrien 1, rtl_dump_file)); 399250615Sobrien if (tem) 399350615Sobrien TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP, 399450615Sobrien !JUMP_NOOP_MOVES, 399550615Sobrien !JUMP_AFTER_REGSCAN)); 399650615Sobrien } 399718334Speter 399850615Sobrien if (flag_thread_jumps) 399950615Sobrien { 400050615Sobrien /* This pass of jump threading straightens out code 400150615Sobrien that was kinked by loop optimization. */ 400250615Sobrien TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0)); 400350615Sobrien TIMEVAR (jump_time, thread_jumps (insns, max_reg_num (), 0)); 400450615Sobrien } 400552558Sobrien 400650615Sobrien /* Dump rtl code after cse, if we are doing that. */ 400752558Sobrien 400850615Sobrien if (cse2_dump) 400952558Sobrien { 401052558Sobrien close_dump_file (print_rtl, insns); 401152558Sobrien if (graph_dump_format != no_graph) 401252558Sobrien print_rtl_graph_with_bb (dump_base_name, ".cse2", insns); 401352558Sobrien } 401418334Speter } 401552558Sobrien 401650615Sobrien if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities) 401750615Sobrien { 401850615Sobrien if (branch_prob_dump) 401950615Sobrien open_dump_file (".bp", decl_printable_name (decl, 2)); 402052558Sobrien 402150615Sobrien TIMEVAR 402250615Sobrien (branch_prob_time, 402350615Sobrien { 402450615Sobrien branch_prob (insns, rtl_dump_file); 402550615Sobrien }); 402652558Sobrien 402750615Sobrien if (branch_prob_dump) 402852558Sobrien { 402952558Sobrien close_dump_file (print_rtl, insns); 403052558Sobrien if (graph_dump_format != no_graph) 403152558Sobrien print_rtl_graph_with_bb (dump_base_name, ".bp", insns); 403252558Sobrien } 403350615Sobrien } 403452558Sobrien 403518334Speter /* We are no longer anticipating cse in this function, at least. */ 403618334Speter 403718334Speter cse_not_expected = 1; 403818334Speter 403918334Speter /* Now we choose between stupid (pcc-like) register allocation 404018334Speter (if we got the -noreg switch and not -opt) 404118334Speter and smart register allocation. */ 404218334Speter 404352558Sobrien if (optimize > 0) /* Stupid allocation probably won't work */ 404418334Speter obey_regdecls = 0; /* if optimizations being done. */ 404518334Speter 404618334Speter regclass_init (); 404718334Speter 404818334Speter /* Print function header into flow dump now 404918334Speter because doing the flow analysis makes some of the dump. */ 405018334Speter 405118334Speter if (flow_dump) 405250615Sobrien open_dump_file (".flow", decl_printable_name (decl, 2)); 405350615Sobrien 405418334Speter if (obey_regdecls) 405518334Speter { 405618334Speter TIMEVAR (flow_time, 405718334Speter { 405818334Speter regclass (insns, max_reg_num ()); 405918334Speter stupid_life_analysis (insns, max_reg_num (), 406050615Sobrien rtl_dump_file); 406118334Speter }); 406218334Speter } 406318334Speter else 406418334Speter { 406518334Speter /* Do control and data flow analysis, 406618334Speter and write some of the results to dump file. */ 406718334Speter 406850615Sobrien TIMEVAR 406950615Sobrien (flow_time, 407050615Sobrien { 407150615Sobrien find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1); 407252558Sobrien life_analysis (insns, max_reg_num (), rtl_dump_file, 1); 407350615Sobrien }); 407450615Sobrien 407518334Speter if (warn_uninitialized) 407618334Speter { 407718334Speter uninitialized_vars_warning (DECL_INITIAL (decl)); 407818334Speter setjmp_args_warning (); 407918334Speter } 408018334Speter } 408118334Speter 408218334Speter /* Dump rtl after flow analysis. */ 408318334Speter 408418334Speter if (flow_dump) 408552558Sobrien { 408652558Sobrien close_dump_file (print_rtl_with_bb, insns); 408752558Sobrien if (graph_dump_format != no_graph) 408852558Sobrien print_rtl_graph_with_bb (dump_base_name, ".flow", insns); 408952558Sobrien } 409052558Sobrien 409152558Sobrien /* The first life analysis pass has finished. From now on we can not 409252558Sobrien generate any new pseudos. */ 409352558Sobrien no_new_pseudos = 1; 409452558Sobrien 409518334Speter /* If -opt, try combining insns through substitution. */ 409618334Speter 409718334Speter if (optimize > 0) 409850615Sobrien { 409950615Sobrien TIMEVAR (combine_time, combine_instructions (insns, max_reg_num ())); 410052558Sobrien 410150615Sobrien /* Dump rtl code after insn combination. */ 410252558Sobrien 410350615Sobrien if (combine_dump) 410452558Sobrien { 410552558Sobrien dump_rtl (".combine", decl, print_rtl_with_bb, insns); 410652558Sobrien if (graph_dump_format != no_graph) 410752558Sobrien print_rtl_graph_with_bb (dump_base_name, ".combine", insns); 410852558Sobrien } 410950615Sobrien } 411018334Speter 411150615Sobrien /* Register allocation pre-pass, to reduce number of moves 411250615Sobrien necessary for two-address machines. */ 411350615Sobrien if (optimize > 0 && (flag_regmove || flag_expensive_optimizations)) 411450615Sobrien { 411550615Sobrien if (regmove_dump) 411650615Sobrien open_dump_file (".regmove", decl_printable_name (decl, 2)); 411752558Sobrien 411850615Sobrien TIMEVAR (regmove_time, regmove_optimize (insns, max_reg_num (), 411950615Sobrien rtl_dump_file)); 412052558Sobrien 412150615Sobrien if (regmove_dump) 412252558Sobrien { 412352558Sobrien close_dump_file (print_rtl_with_bb, insns); 412452558Sobrien if (graph_dump_format != no_graph) 412552558Sobrien print_rtl_graph_with_bb (dump_base_name, ".regmove", insns); 412652558Sobrien } 412750615Sobrien } 412818334Speter 412918334Speter /* Print function header into sched dump now 413018334Speter because doing the sched analysis makes some of the dump. */ 413118334Speter 413218334Speter if (optimize > 0 && flag_schedule_insns) 413318334Speter { 413450615Sobrien if (sched_dump) 413550615Sobrien open_dump_file (".sched", decl_printable_name (decl, 2)); 413652558Sobrien 413718334Speter /* Do control and data sched analysis, 413818334Speter and write some of the results to dump file. */ 413918334Speter 414050615Sobrien TIMEVAR (sched_time, schedule_insns (rtl_dump_file)); 414152558Sobrien 414250615Sobrien /* Dump rtl after instruction scheduling. */ 414352558Sobrien 414450615Sobrien if (sched_dump) 414552558Sobrien { 414652558Sobrien close_dump_file (print_rtl_with_bb, insns); 414752558Sobrien if (graph_dump_format != no_graph) 414852558Sobrien print_rtl_graph_with_bb (dump_base_name, ".sched", insns); 414952558Sobrien } 415018334Speter } 415118334Speter 415252558Sobrien /* Determine if the current function is a leaf before running reload 415352558Sobrien since this can impact optimizations done by the prologue and 415452558Sobrien epilogue thus changing register elimination offsets. */ 415552558Sobrien current_function_is_leaf = leaf_function_p (); 415652558Sobrien 415718334Speter /* Unless we did stupid register allocation, 415852558Sobrien allocate pseudo-regs that are used only within 1 basic block. 415918334Speter 416052558Sobrien RUN_JUMP_AFTER_RELOAD records whether or not we need to rerun the 416152558Sobrien jump optimizer after register allocation and reloading are finished. */ 416252558Sobrien 416318334Speter if (!obey_regdecls) 416418334Speter TIMEVAR (local_alloc_time, 416518334Speter { 416652558Sobrien recompute_reg_usage (insns, ! optimize_size); 416718334Speter regclass (insns, max_reg_num ()); 416852558Sobrien rebuild_label_notes_after_reload = local_alloc (); 416918334Speter }); 417052558Sobrien else 417152558Sobrien rebuild_label_notes_after_reload = 0; 417218334Speter 417318334Speter /* Dump rtl code after allocating regs within basic blocks. */ 417418334Speter 417518334Speter if (local_reg_dump) 417650615Sobrien { 417750615Sobrien open_dump_file (".lreg", decl_printable_name (decl, 2)); 417852558Sobrien 417950615Sobrien TIMEVAR (dump_time, dump_flow_info (rtl_dump_file)); 418050615Sobrien TIMEVAR (dump_time, dump_local_alloc (rtl_dump_file)); 418152558Sobrien 418250615Sobrien close_dump_file (print_rtl_with_bb, insns); 418352558Sobrien if (graph_dump_format != no_graph) 418452558Sobrien print_rtl_graph_with_bb (dump_base_name, ".lreg", insns); 418550615Sobrien } 418618334Speter 418718334Speter if (global_reg_dump) 418850615Sobrien open_dump_file (".greg", decl_printable_name (decl, 2)); 418918334Speter 419018334Speter /* Unless we did stupid register allocation, 419118334Speter allocate remaining pseudo-regs, then do the reload pass 419218334Speter fixing up any insns that are invalid. */ 419318334Speter 419418334Speter TIMEVAR (global_alloc_time, 419518334Speter { 419618334Speter if (!obey_regdecls) 419750615Sobrien failure = global_alloc (rtl_dump_file); 419818334Speter else 419950615Sobrien failure = reload (insns, 0, rtl_dump_file); 420018334Speter }); 420118334Speter 420218334Speter 420318334Speter if (failure) 420418334Speter goto exit_rest_of_compilation; 420518334Speter 420650615Sobrien /* Do a very simple CSE pass over just the hard registers. */ 420750615Sobrien if (optimize > 0) 420850615Sobrien reload_cse_regs (insns); 420950615Sobrien 421052558Sobrien /* Register allocation and reloading may have turned an indirect jump into 421152558Sobrien a direct jump. If so, we must rebuild the JUMP_LABEL fields of 421252558Sobrien jumping instructions. */ 421352558Sobrien if (rebuild_label_notes_after_reload) 421452558Sobrien TIMEVAR (jump_time, rebuild_jump_labels (insns)); 421552558Sobrien 421652558Sobrien /* If optimizing and we are performing instruction scheduling after 421752558Sobrien reload, then go ahead and split insns now since we are about to 421852558Sobrien recompute flow information anyway. 421952558Sobrien 422052558Sobrien reload_cse_regs may expose more splitting opportunities, expecially 422152558Sobrien for double-word operations. */ 422252558Sobrien if (optimize > 0 && flag_schedule_insns_after_reload) 422352558Sobrien { 422452558Sobrien rtx insn; 422552558Sobrien 422652558Sobrien for (insn = insns; insn; insn = NEXT_INSN (insn)) 422752558Sobrien { 422852558Sobrien rtx last; 422952558Sobrien 423052558Sobrien if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') 423152558Sobrien continue; 423252558Sobrien 423352558Sobrien last = try_split (PATTERN (insn), insn, 1); 423452558Sobrien 423552558Sobrien if (last != insn) 423652558Sobrien { 423752558Sobrien PUT_CODE (insn, NOTE); 423852558Sobrien NOTE_SOURCE_FILE (insn) = 0; 423952558Sobrien NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; 424052558Sobrien } 424152558Sobrien } 424252558Sobrien } 424352558Sobrien 424452558Sobrien if (global_reg_dump) 424552558Sobrien { 424652558Sobrien TIMEVAR (dump_time, dump_global_regs (rtl_dump_file)); 424752558Sobrien close_dump_file (print_rtl_with_bb, insns); 424852558Sobrien if (graph_dump_format != no_graph) 424952558Sobrien print_rtl_graph_with_bb (dump_base_name, ".greg", insns); 425052558Sobrien } 425152558Sobrien 425252558Sobrien /* Re-create the death notes which were deleted during reload. */ 425352558Sobrien if (flow2_dump) 425452558Sobrien open_dump_file (".flow2", decl_printable_name (decl, 2)); 425552558Sobrien 425652558Sobrien if (optimize) 425752558Sobrien { 425852558Sobrien TIMEVAR 425952558Sobrien (flow2_time, 426052558Sobrien { 426152558Sobrien find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1); 426252558Sobrien life_analysis (insns, max_reg_num (), rtl_dump_file, 1); 426352558Sobrien }); 426452558Sobrien } 426552558Sobrien 426652558Sobrien flow2_completed = 1; 426752558Sobrien 426818334Speter /* On some machines, the prologue and epilogue code, or parts thereof, 426918334Speter can be represented as RTL. Doing so lets us schedule insns between 427018334Speter it and the rest of the code and also allows delayed branch 427118334Speter scheduling to operate in the epilogue. */ 427218334Speter 427318334Speter thread_prologue_and_epilogue_insns (insns); 427418334Speter 427552558Sobrien if (flow2_dump) 427650615Sobrien { 427750615Sobrien close_dump_file (print_rtl_with_bb, insns); 427852558Sobrien if (graph_dump_format != no_graph) 427952558Sobrien print_rtl_graph_with_bb (dump_base_name, ".flow2", insns); 428050615Sobrien } 428152558Sobrien 428218334Speter if (optimize > 0 && flag_schedule_insns_after_reload) 428318334Speter { 428418334Speter if (sched2_dump) 428550615Sobrien open_dump_file (".sched2", decl_printable_name (decl, 2)); 428618334Speter 428718334Speter /* Do control and data sched analysis again, 428818334Speter and write some more of the results to dump file. */ 428918334Speter 429050615Sobrien TIMEVAR (sched2_time, schedule_insns (rtl_dump_file)); 429118334Speter 429218334Speter /* Dump rtl after post-reorder instruction scheduling. */ 429318334Speter 429418334Speter if (sched2_dump) 429552558Sobrien { 429652558Sobrien close_dump_file (print_rtl_with_bb, insns); 429752558Sobrien if (graph_dump_format != no_graph) 429852558Sobrien print_rtl_graph_with_bb (dump_base_name, ".sched2", insns); 429952558Sobrien } 430018334Speter } 430118334Speter 430218334Speter#ifdef LEAF_REGISTERS 430352558Sobrien current_function_uses_only_leaf_regs 430452558Sobrien = optimize > 0 && only_leaf_regs_used () && leaf_function_p (); 430518334Speter#endif 430618334Speter 430718334Speter /* One more attempt to remove jumps to .+1 430818334Speter left by dead-store-elimination. 430918334Speter Also do cross-jumping this time 431018334Speter and delete no-op move insns. */ 431118334Speter 431218334Speter if (optimize > 0) 431318334Speter { 431450615Sobrien TIMEVAR (jump_time, jump_optimize (insns, JUMP_CROSS_JUMP, 431550615Sobrien JUMP_NOOP_MOVES, 431650615Sobrien !JUMP_AFTER_REGSCAN)); 431752558Sobrien 431850615Sobrien /* Dump rtl code after jump, if we are doing that. */ 431950615Sobrien 432050615Sobrien if (jump2_opt_dump) 432152558Sobrien { 432252558Sobrien dump_rtl (".jump2", decl, print_rtl_with_bb, insns); 432352558Sobrien if (graph_dump_format != no_graph) 432452558Sobrien print_rtl_graph_with_bb (dump_base_name, ".jump2", insns); 432552558Sobrien } 432618334Speter } 432718334Speter 432818334Speter /* If a machine dependent reorganization is needed, call it. */ 432918334Speter#ifdef MACHINE_DEPENDENT_REORG 433018334Speter MACHINE_DEPENDENT_REORG (insns); 433150615Sobrien 433250615Sobrien if (mach_dep_reorg_dump) 433352558Sobrien { 433452558Sobrien dump_rtl (".mach", decl, print_rtl_with_bb, insns); 433552558Sobrien if (graph_dump_format != no_graph) 433652558Sobrien print_rtl_graph_with_bb (dump_base_name, ".mach", insns); 433752558Sobrien } 433818334Speter#endif 433918334Speter 434018334Speter /* If a scheduling pass for delayed branches is to be done, 434150615Sobrien call the scheduling code. */ 434218334Speter 434318334Speter#ifdef DELAY_SLOTS 434418334Speter if (optimize > 0 && flag_delayed_branch) 434518334Speter { 434652558Sobrien if (dbr_sched_dump) 434752558Sobrien open_dump_file (".dbr", decl_printable_name (decl, 2)); 434852558Sobrien 434950615Sobrien TIMEVAR (dbr_sched_time, dbr_schedule (insns, rtl_dump_file)); 435052558Sobrien 435118334Speter if (dbr_sched_dump) 435252558Sobrien { 435352558Sobrien close_dump_file (print_rtl_with_bb, insns); 435452558Sobrien if (graph_dump_format != no_graph) 435552558Sobrien print_rtl_graph_with_bb (dump_base_name, ".dbr", insns); 435652558Sobrien } 435718334Speter } 435818334Speter#endif 435918334Speter 436018334Speter /* Shorten branches. */ 436118334Speter TIMEVAR (shorten_branch_time, 436218334Speter { 436318334Speter shorten_branches (get_insns ()); 436418334Speter }); 436518334Speter 436618334Speter#ifdef STACK_REGS 436752558Sobrien if (stack_reg_dump) 436852558Sobrien open_dump_file (".stack", decl_printable_name (decl, 2)); 436952558Sobrien 437050615Sobrien TIMEVAR (stack_reg_time, reg_to_stack (insns, rtl_dump_file)); 437150615Sobrien 437218334Speter if (stack_reg_dump) 437352558Sobrien { 437452558Sobrien dump_rtl (".stack", decl, print_rtl_with_bb, insns); 437552558Sobrien if (graph_dump_format != no_graph) 437652558Sobrien print_rtl_graph_with_bb (dump_base_name, ".stack", insns); 437752558Sobrien } 437818334Speter#endif 437918334Speter 438018334Speter /* Now turn the rtl into assembler code. */ 438118334Speter 438218334Speter TIMEVAR (final_time, 438318334Speter { 438418334Speter rtx x; 438518334Speter char *fnname; 438618334Speter 438718334Speter /* Get the function's name, as described by its RTL. 438818334Speter This may be different from the DECL_NAME name used 438918334Speter in the source file. */ 439018334Speter 439118334Speter x = DECL_RTL (decl); 439218334Speter if (GET_CODE (x) != MEM) 439318334Speter abort (); 439418334Speter x = XEXP (x, 0); 439518334Speter if (GET_CODE (x) != SYMBOL_REF) 439618334Speter abort (); 439718334Speter fnname = XSTR (x, 0); 439818334Speter 439918334Speter assemble_start_function (decl, fnname); 440018334Speter final_start_function (insns, asm_out_file, optimize); 440118334Speter final (insns, asm_out_file, optimize, 0); 440218334Speter final_end_function (insns, asm_out_file, optimize); 440318334Speter assemble_end_function (decl, fnname); 440450615Sobrien if (! quiet_flag) 440550615Sobrien fflush (asm_out_file); 440650615Sobrien 440752558Sobrien /* Release all memory allocated by flow. */ 440852558Sobrien free_basic_block_vars (0); 440952558Sobrien 441050615Sobrien /* Release all memory held by regsets now */ 441150615Sobrien regset_release_memory (); 441218334Speter }); 441318334Speter 441418334Speter /* Write DBX symbols if requested */ 441518334Speter 441618334Speter /* Note that for those inline functions where we don't initially 441718334Speter know for certain that we will be generating an out-of-line copy, 441818334Speter the first invocation of this routine (rest_of_compilation) will 441918334Speter skip over this code by doing a `goto exit_rest_of_compilation;'. 442018334Speter Later on, finish_compilation will call rest_of_compilation again 442118334Speter for those inline functions that need to have out-of-line copies 442218334Speter generated. During that call, we *will* be routed past here. */ 442318334Speter 442418334Speter#ifdef DBX_DEBUGGING_INFO 442518334Speter if (write_symbols == DBX_DEBUG) 442618334Speter TIMEVAR (symout_time, dbxout_function (decl)); 442718334Speter#endif 442818334Speter 442918334Speter#ifdef DWARF_DEBUGGING_INFO 443018334Speter if (write_symbols == DWARF_DEBUG) 443118334Speter TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 0)); 443218334Speter#endif 443318334Speter 443450615Sobrien#ifdef DWARF2_DEBUGGING_INFO 443550615Sobrien if (write_symbols == DWARF2_DEBUG) 443650615Sobrien TIMEVAR (symout_time, dwarf2out_decl (decl)); 443750615Sobrien#endif 443850615Sobrien 443918334Speter exit_rest_of_compilation: 444018334Speter 444152558Sobrien free_bb_mem (); 444252558Sobrien 444318334Speter /* In case the function was not output, 444418334Speter don't leave any temporary anonymous types 444518334Speter queued up for sdb output. */ 444618334Speter#ifdef SDB_DEBUGGING_INFO 444718334Speter if (write_symbols == SDB_DEBUG) 444818334Speter sdbout_types (NULL_TREE); 444918334Speter#endif 445018334Speter 445118334Speter /* Put back the tree of subblocks and list of arguments 445218334Speter from before we copied them. 445318334Speter Code generation and the output of debugging info may have modified 445418334Speter the copy, but the original is unchanged. */ 445518334Speter 445618334Speter if (saved_block_tree != 0) 445750615Sobrien { 445850615Sobrien DECL_INITIAL (decl) = saved_block_tree; 445950615Sobrien DECL_ARGUMENTS (decl) = saved_arguments; 446050615Sobrien DECL_ABSTRACT_ORIGIN (decl) = NULL_TREE; 446150615Sobrien } 446218334Speter 446318334Speter reload_completed = 0; 446452558Sobrien flow2_completed = 0; 446552558Sobrien no_new_pseudos = 0; 446618334Speter 446750615Sobrien TIMEVAR (final_time, 446850615Sobrien { 446950615Sobrien /* Clear out the insn_length contents now that they are no 447050615Sobrien longer valid. */ 447150615Sobrien init_insn_lengths (); 447218334Speter 447350615Sobrien /* Clear out the real_constant_chain before some of the rtx's 447450615Sobrien it runs through become garbage. */ 447550615Sobrien clear_const_double_mem (); 447618334Speter 447750615Sobrien /* Cancel the effect of rtl_in_current_obstack. */ 447850615Sobrien resume_temporary_allocation (); 447918334Speter 448050615Sobrien /* Show no temporary slots allocated. */ 448150615Sobrien init_temp_slots (); 448250615Sobrien }); 448318334Speter 448450615Sobrien /* Make sure volatile mem refs aren't considered valid operands for 448550615Sobrien arithmetic insns. We must call this here if this is a nested inline 448650615Sobrien function, since the above code leaves us in the init_recog state 448750615Sobrien (from final.c), and the function context push/pop code does not 448850615Sobrien save/restore volatile_ok. 448918334Speter 449050615Sobrien ??? Maybe it isn't necessary for expand_start_function to call this 449150615Sobrien anymore if we do it here? */ 449250615Sobrien 449350615Sobrien init_recog_no_volatile (); 449450615Sobrien 449518334Speter /* The parsing time is all the time spent in yyparse 449618334Speter *except* what is spent in this function. */ 449718334Speter 449818334Speter parse_time -= get_run_time () - start_time; 449952558Sobrien 450052558Sobrien /* Reset global variables. */ 450152558Sobrien free_basic_block_vars (0); 450218334Speter} 450318334Speter 450450615Sobrienstatic void 450550615Sobriendisplay_help () 450650615Sobrien{ 450750615Sobrien int undoc; 450852558Sobrien unsigned long i; 450952558Sobrien const char * lang; 451052558Sobrien 451152558Sobrien#ifndef USE_CPPLIB 451250615Sobrien printf ("Usage: %s input [switches]\n", progname); 451350615Sobrien printf ("Switches:\n"); 451450615Sobrien#endif 451550615Sobrien printf (" -ffixed-<register> Mark <register> as being unavailable to the compiler\n"); 451650615Sobrien printf (" -fcall-used-<register> Mark <register> as being corrupted by function calls\n"); 451750615Sobrien printf (" -fcall-saved-<register> Mark <register> as being preserved across functions\n"); 451852558Sobrien printf (" -finline-limit-<number> Limits the size of inlined functions to <number>\n"); 451950615Sobrien 452050615Sobrien for (i = NUM_ELEM (f_options); i--;) 452150615Sobrien { 452252558Sobrien const char * description = f_options[i].description; 452350615Sobrien 452450615Sobrien if (description != NULL && * description != 0) 452550615Sobrien printf (" -f%-21s %s\n", 452650615Sobrien f_options[i].string, description); 452750615Sobrien } 452850615Sobrien 452950615Sobrien printf (" -O[number] Set optimisation level to [number]\n"); 453050615Sobrien printf (" -Os Optimise for space rather than speed\n"); 453150615Sobrien printf (" -pedantic Issue warnings needed by strict compliance to ANSI C\n"); 453250615Sobrien printf (" -pedantic-errors Like -pedantic except that errors are produced\n"); 453350615Sobrien printf (" -w Suppress warnings\n"); 453450615Sobrien printf (" -W Enable extra warnings\n"); 453550615Sobrien 453650615Sobrien for (i = NUM_ELEM (W_options); i--;) 453750615Sobrien { 453852558Sobrien const char * description = W_options[i].description; 453950615Sobrien 454050615Sobrien if (description != NULL && * description != 0) 454150615Sobrien printf (" -W%-21s %s\n", 454250615Sobrien W_options[i].string, description); 454350615Sobrien } 454450615Sobrien 454550615Sobrien printf (" -Wid-clash-<num> Warn if 2 identifiers have the same first <num> chars\n"); 454650615Sobrien printf (" -Wlarger-than-<number> Warn if an object is larger than <number> bytes\n"); 454750615Sobrien printf (" -p Enable function profiling\n"); 454850615Sobrien#if defined (BLOCK_PROFILER) || defined (FUNCTION_BLOCK_PROFILER) 454950615Sobrien printf (" -a Enable block profiling \n"); 455050615Sobrien#endif 455150615Sobrien#if defined (BLOCK_PROFILER) || defined (FUNCTION_BLOCK_PROFILER) || defined FUNCTION_BLOCK_PROFILER_EXIT 455250615Sobrien printf (" -ax Enable jump profiling \n"); 455350615Sobrien#endif 455450615Sobrien printf (" -o <file> Place output into <file> \n"); 455550615Sobrien printf (" -G <number> Put global and static data smaller than <number>\n"); 455650615Sobrien printf (" bytes into a special section (on some targets)\n"); 455750615Sobrien 455850615Sobrien for (i = NUM_ELEM (debug_args); i--;) 455950615Sobrien { 456050615Sobrien if (debug_args[i].description != NULL) 456150615Sobrien printf (" -%-22s %s\n", debug_args[i].arg, debug_args[i].description); 456250615Sobrien } 456350615Sobrien 456450615Sobrien printf (" -aux-info <file> Emit declaration info into <file>.X\n"); 456550615Sobrien printf (" -quiet Do not display functions compiled or elapsed time\n"); 456650615Sobrien printf (" -version Display the compiler's version\n"); 456750615Sobrien printf (" -d[letters] Enable dumps from specific passes of the compiler\n"); 456850615Sobrien printf (" -dumpbase <file> Base name to be used for dumps from specific passes\n"); 456950615Sobrien#if defined HAIFA || defined INSN_SCHEDULING 457050615Sobrien printf (" -sched-verbose-<number> Set the verbosity level of the scheduler\n"); 457150615Sobrien#endif 457250615Sobrien printf (" --help Display this information\n"); 457350615Sobrien 457450615Sobrien undoc = 0; 457550615Sobrien lang = "language"; 457650615Sobrien 457750615Sobrien /* Display descriptions of language specific options. 457850615Sobrien If there is no description, note that there is an undocumented option. 457950615Sobrien If the description is empty, do not display anything. (This allows 458050615Sobrien options to be deliberately undocumented, for whatever reason). 458150615Sobrien If the option string is missing, then this is a marker, indicating 458252558Sobrien that the description string is in fact the name of a language, whose 458350615Sobrien language specific options are to follow. */ 458450615Sobrien 458550615Sobrien if (NUM_ELEM (documented_lang_options) > 1) 458650615Sobrien { 458750615Sobrien printf ("\nLanguage specific options:\n"); 458850615Sobrien 458950615Sobrien for (i = 0; i < NUM_ELEM (documented_lang_options); i++) 459050615Sobrien { 459152558Sobrien const char * description = documented_lang_options[i].description; 459252558Sobrien const char * option = documented_lang_options[i].option; 459350615Sobrien 459450615Sobrien if (description == NULL) 459552558Sobrien { 459652558Sobrien undoc = 1; 459752558Sobrien 459852558Sobrien if (extra_warnings) 459952558Sobrien printf (" %-23.23s [undocumented]\n", option); 460052558Sobrien } 460150615Sobrien else if (* description == 0) 460250615Sobrien continue; 460350615Sobrien else if (option == NULL) 460450615Sobrien { 460550615Sobrien if (undoc) 460650615Sobrien printf 460750615Sobrien ("\nThere are undocumented %s specific options as well.\n", 460850615Sobrien lang); 460950615Sobrien undoc = 0; 461050615Sobrien 461150615Sobrien printf ("\n Options for %s:\n", description); 461250615Sobrien 461350615Sobrien lang = description; 461450615Sobrien } 461550615Sobrien else 461650615Sobrien printf (" %-23.23s %s\n", option, description); 461750615Sobrien } 461850615Sobrien } 461950615Sobrien 462050615Sobrien if (undoc) 462150615Sobrien printf ("\nThere are undocumented %s specific options as well.\n", lang); 462250615Sobrien 462350615Sobrien if (NUM_ELEM (target_switches) > 1 462450615Sobrien#ifdef TARGET_OPTIONS 462550615Sobrien || NUM_ELEM (target_options) > 1 462650615Sobrien#endif 462750615Sobrien ) 462850615Sobrien { 462950615Sobrien int doc = 0; 463050615Sobrien 463150615Sobrien undoc = 0; 463250615Sobrien 463350615Sobrien printf ("\nTarget specific options:\n"); 463450615Sobrien 463550615Sobrien for (i = NUM_ELEM (target_switches); i--;) 463650615Sobrien { 463752558Sobrien const char * option = target_switches[i].name; 463852558Sobrien const char * description = target_switches[i].description; 463950615Sobrien 464052558Sobrien if (option == NULL || * option == 0) 464150615Sobrien continue; 464250615Sobrien else if (description == NULL) 464352558Sobrien { 464452558Sobrien undoc = 1; 464552558Sobrien 464652558Sobrien if (extra_warnings) 464752558Sobrien printf (" -m%-21.21s [undocumented]\n", option); 464852558Sobrien } 464950615Sobrien else if (* description != 0) 465052558Sobrien doc += printf (" -m%-21.21s %s\n", option, description); 465150615Sobrien } 465250615Sobrien 465350615Sobrien#ifdef TARGET_OPTIONS 465450615Sobrien for (i = NUM_ELEM (target_options); i--;) 465550615Sobrien { 465652558Sobrien const char * option = target_options[i].prefix; 465752558Sobrien const char * description = target_options[i].description; 465850615Sobrien 465952558Sobrien if (option == NULL || * option == 0) 466050615Sobrien continue; 466150615Sobrien else if (description == NULL) 466252558Sobrien { 466352558Sobrien undoc = 1; 466452558Sobrien 466552558Sobrien if (extra_warnings) 466652558Sobrien printf (" -m%-21.21s [undocumented]\n", option); 466752558Sobrien } 466850615Sobrien else if (* description != 0) 466952558Sobrien doc += printf (" -m%-21.21s %s\n", option, description); 467050615Sobrien } 467150615Sobrien#endif 467250615Sobrien if (undoc) 467352558Sobrien { 467452558Sobrien if (doc) 467552558Sobrien printf ("\nThere are undocumented target specific options as well.\n"); 467652558Sobrien else 467752558Sobrien printf (" They exist, but they are not documented.\n"); 467852558Sobrien } 467950615Sobrien } 468050615Sobrien} 468150615Sobrien 468250615Sobrien/* Compare the user specified 'option' with the language 468350615Sobrien specific 'lang_option'. Return true if they match, or 468450615Sobrien if 'option' is a viable prefix of 'lang_option'. */ 468550615Sobrien 468650615Sobrienstatic int 468750615Sobriencheck_lang_option (option, lang_option) 468850615Sobrien char * option; 468950615Sobrien char * lang_option; 469050615Sobrien{ 469150615Sobrien lang_independent_options * indep_options; 469250615Sobrien int len; 469350615Sobrien long k; 469452558Sobrien char * space; 469552558Sobrien 469650615Sobrien /* Ignore NULL entries. */ 469750615Sobrien if (option == NULL || lang_option == NULL) 469850615Sobrien return 0; 469950615Sobrien 470052558Sobrien if ((space = strchr (lang_option, ' ')) != NULL) 470152558Sobrien len = space - lang_option; 470252558Sobrien else 470352558Sobrien len = strlen (lang_option); 470452558Sobrien 470550615Sobrien /* If they do not match to the first n characters then fail. */ 470650615Sobrien if (strncmp (option, lang_option, len) != 0) 470750615Sobrien return 0; 470852558Sobrien 470950615Sobrien /* Do not accept a lang option, if it matches a normal -f or -W 471050615Sobrien option. Chill defines a -fpack, but we want to support 471150615Sobrien -fpack-struct. */ 471252558Sobrien 471350615Sobrien /* An exact match is OK */ 471452558Sobrien if ((int) strlen (option) == len) 471550615Sobrien return 1; 471652558Sobrien 471750615Sobrien /* If it is not an -f or -W option allow the match */ 471850615Sobrien if (option[0] != '-') 471950615Sobrien return 1; 472052558Sobrien 472150615Sobrien switch (option[1]) 472250615Sobrien { 472350615Sobrien case 'f': indep_options = f_options; break; 472450615Sobrien case 'W': indep_options = W_options; break; 472550615Sobrien default: return 1; 472650615Sobrien } 472752558Sobrien 472850615Sobrien /* The option is a -f or -W option. 472950615Sobrien Skip past the prefix and search for the remainder in the 473050615Sobrien appropriate table of options. */ 473150615Sobrien option += 2; 473252558Sobrien 473350615Sobrien if (option[0] == 'n' && option[1] == 'o' && option[2] == '-') 473450615Sobrien option += 3; 473552558Sobrien 473650615Sobrien for (k = NUM_ELEM (indep_options); k--;) 473750615Sobrien { 473850615Sobrien if (!strcmp (option, indep_options[k].string)) 473950615Sobrien { 474050615Sobrien /* The option matched a language independent option, 474150615Sobrien do not allow the language specific match. */ 474252558Sobrien 474350615Sobrien return 0; 474450615Sobrien } 474550615Sobrien } 474652558Sobrien 474750615Sobrien /* The option matches the start of the langauge specific option 474850615Sobrien and it is not an exact match for a language independent option. */ 474950615Sobrien return 1; 475050615Sobrien} 475150615Sobrien 475218334Speter/* Entry point of cc1/c++. Decode command args, then call compile_file. 475318334Speter Exit code is 35 if can't open files, 34 if fatal error, 475418334Speter 33 if had nonfatal errors, else success. */ 475518334Speter 475618334Speterint 475752558Sobrienmain (argc, argv) 475818334Speter int argc; 475918334Speter char **argv; 476018334Speter{ 476118334Speter register int i; 476218334Speter char *filename = 0; 476318334Speter int flag_print_mem = 0; 476418334Speter int version_flag = 0; 476518334Speter char *p; 476618334Speter 476718334Speter /* save in case md file wants to emit args as a comment. */ 476818334Speter save_argc = argc; 476918334Speter save_argv = argv; 477018334Speter 477118334Speter p = argv[0] + strlen (argv[0]); 477218334Speter while (p != argv[0] && p[-1] != '/' 477318334Speter#ifdef DIR_SEPARATOR 477418334Speter && p[-1] != DIR_SEPARATOR 477518334Speter#endif 477618334Speter ) 477718334Speter --p; 477818334Speter progname = p; 477918334Speter 478050615Sobrien#if defined (RLIMIT_STACK) && defined (HAVE_GETRLIMIT) && defined (HAVE_SETRLIMIT) 478118334Speter /* Get rid of any avoidable limit on stack size. */ 478218334Speter { 478318334Speter struct rlimit rlim; 478418334Speter 478550615Sobrien /* Set the stack limit huge so that alloca does not fail. */ 478618334Speter getrlimit (RLIMIT_STACK, &rlim); 478718334Speter rlim.rlim_cur = rlim.rlim_max; 478818334Speter setrlimit (RLIMIT_STACK, &rlim); 478918334Speter } 479050615Sobrien#endif 479118334Speter 479252558Sobrien#ifdef HAVE_LC_MESSAGES 479352558Sobrien setlocale (LC_MESSAGES, ""); 479452558Sobrien#endif 479552558Sobrien (void) bindtextdomain (PACKAGE, localedir); 479652558Sobrien (void) textdomain (PACKAGE); 479752558Sobrien 479818334Speter signal (SIGFPE, float_signal); 479918334Speter 480018334Speter#ifdef SIGPIPE 480118334Speter signal (SIGPIPE, pipe_closed); 480218334Speter#endif 480318334Speter 480418334Speter decl_printable_name = decl_name; 480552558Sobrien lang_expand_expr = (lang_expand_expr_t) do_abort; 480618334Speter 480718334Speter /* Initialize whether `char' is signed. */ 480818334Speter flag_signed_char = DEFAULT_SIGNED_CHAR; 480918334Speter#ifdef DEFAULT_SHORT_ENUMS 481018334Speter /* Initialize how much space enums occupy, by default. */ 481118334Speter flag_short_enums = DEFAULT_SHORT_ENUMS; 481218334Speter#endif 481318334Speter 481450615Sobrien /* Perform language-specific options intialization. */ 481550615Sobrien lang_init_options (); 481650615Sobrien 481718334Speter /* Scan to see what optimization level has been specified. That will 481818334Speter determine the default value of many flags. */ 481918334Speter for (i = 1; i < argc; i++) 482018334Speter { 482118334Speter if (!strcmp (argv[i], "-O")) 482218334Speter { 482318334Speter optimize = 1; 482452558Sobrien optimize_size = 0; 482518334Speter } 482618334Speter else if (argv[i][0] == '-' && argv[i][1] == 'O') 482718334Speter { 482850615Sobrien /* Handle -Os, -O2, -O3, -O69, ... */ 482918334Speter char *p = &argv[i][2]; 483050615Sobrien 483150615Sobrien if ((p[0] == 's') && (p[1] == 0)) 483252558Sobrien { 483352558Sobrien optimize_size = 1; 483452558Sobrien 483552558Sobrien /* Optimizing for size forces optimize to be 2. */ 483652558Sobrien optimize = 2; 483752558Sobrien } 483850615Sobrien else 483950615Sobrien { 484052558Sobrien const int optimize_val = read_integral_parameter (p, p - 2, -1); 484152558Sobrien if (optimize_val != -1) 484252558Sobrien { 484352558Sobrien optimize = optimize_val; 484452558Sobrien optimize_size = 0; 484552558Sobrien } 484650615Sobrien } 484718334Speter } 484818334Speter } 484918334Speter 485018334Speter obey_regdecls = (optimize == 0); 485118334Speter 485218334Speter if (optimize >= 1) 485318334Speter { 485418334Speter flag_defer_pop = 1; 485518334Speter flag_thread_jumps = 1; 485618334Speter#ifdef DELAY_SLOTS 485718334Speter flag_delayed_branch = 1; 485818334Speter#endif 485918334Speter#ifdef CAN_DEBUG_WITHOUT_FP 486018334Speter flag_omit_frame_pointer = 1; 486118334Speter#endif 486218334Speter } 486318334Speter 486418334Speter if (optimize >= 2) 486518334Speter { 486618334Speter flag_cse_follow_jumps = 1; 486718334Speter flag_cse_skip_blocks = 1; 486850615Sobrien flag_gcse = 1; 486918334Speter flag_expensive_optimizations = 1; 487018334Speter flag_strength_reduce = 1; 487118334Speter flag_rerun_cse_after_loop = 1; 487250615Sobrien flag_rerun_loop_opt = 1; 487318334Speter flag_caller_saves = 1; 487418334Speter flag_force_mem = 1; 487518334Speter#ifdef INSN_SCHEDULING 487618334Speter flag_schedule_insns = 1; 487718334Speter flag_schedule_insns_after_reload = 1; 487818334Speter#endif 487950615Sobrien flag_regmove = 1; 488052558Sobrien flag_strict_aliasing = 1; 488118334Speter } 488218334Speter 488318334Speter if (optimize >= 3) 488418334Speter { 488518334Speter flag_inline_functions = 1; 488618334Speter } 488718334Speter 488850615Sobrien /* Initialize target_flags before OPTIMIZATION_OPTIONS so the latter can 488950615Sobrien modify it. */ 489050615Sobrien target_flags = 0; 489150615Sobrien set_target_switch (""); 489250615Sobrien 489318334Speter#ifdef OPTIMIZATION_OPTIONS 489418334Speter /* Allow default optimizations to be specified on a per-machine basis. */ 489550615Sobrien OPTIMIZATION_OPTIONS (optimize, optimize_size); 489618334Speter#endif 489718334Speter 489818334Speter /* Initialize register usage now so switches may override. */ 489918334Speter init_reg_sets (); 490018334Speter 490118334Speter for (i = 1; i < argc; i++) 490218334Speter { 490350615Sobrien size_t j; 490450615Sobrien 490518334Speter /* If this is a language-specific option, 490618334Speter decode it in a language-specific way. */ 490750615Sobrien for (j = NUM_ELEM (documented_lang_options); j--;) 490850615Sobrien if (check_lang_option (argv[i], documented_lang_options[j].option)) 490918334Speter break; 491050615Sobrien 491152558Sobrien if (j != (size_t)-1) 491250615Sobrien { 491350615Sobrien /* If the option is valid for *some* language, 491450615Sobrien treat it as valid even if this language doesn't understand it. */ 491550615Sobrien int strings_processed = lang_decode_option (argc - i, argv + i); 491650615Sobrien 491750615Sobrien if (!strcmp (argv[i], "--help")) 491850615Sobrien { 491950615Sobrien display_help (); 492050615Sobrien exit (0); 492150615Sobrien } 492250615Sobrien 492350615Sobrien if (strings_processed != 0) 492450615Sobrien i += strings_processed - 1; 492550615Sobrien } 492618334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 492718334Speter { 492818334Speter register char *str = argv[i] + 1; 492918334Speter if (str[0] == 'Y') 493018334Speter str++; 493118334Speter 493218334Speter if (str[0] == 'm') 493318334Speter set_target_switch (&str[1]); 493418334Speter else if (!strcmp (str, "dumpbase")) 493518334Speter { 493618334Speter dump_base_name = argv[++i]; 493718334Speter } 493818334Speter else if (str[0] == 'd') 493918334Speter { 494018334Speter register char *p = &str[1]; 494118334Speter while (*p) 494218334Speter switch (*p++) 494318334Speter { 494418334Speter case 'a': 494550615Sobrien branch_prob_dump = 1; 494618334Speter combine_dump = 1; 494750615Sobrien#ifdef DELAY_SLOTS 494818334Speter dbr_sched_dump = 1; 494950615Sobrien#endif 495018334Speter flow_dump = 1; 495152558Sobrien flow2_dump = 1; 495218334Speter global_reg_dump = 1; 495318334Speter jump_opt_dump = 1; 495450615Sobrien addressof_dump = 1; 495518334Speter jump2_opt_dump = 1; 495618334Speter local_reg_dump = 1; 495718334Speter loop_dump = 1; 495850615Sobrien regmove_dump = 1; 495918334Speter rtl_dump = 1; 496018334Speter cse_dump = 1, cse2_dump = 1; 496150615Sobrien gcse_dump = 1; 496218334Speter sched_dump = 1; 496318334Speter sched2_dump = 1; 496450615Sobrien#ifdef STACK_REGS 496518334Speter stack_reg_dump = 1; 496650615Sobrien#endif 496750615Sobrien#ifdef MACHINE_DEPENDENT_REORG 496850615Sobrien mach_dep_reorg_dump = 1; 496950615Sobrien#endif 497018334Speter break; 497150615Sobrien case 'A': 497250615Sobrien flag_debug_asm = 1; 497318334Speter break; 497450615Sobrien case 'b': 497550615Sobrien branch_prob_dump = 1; 497650615Sobrien break; 497718334Speter case 'c': 497818334Speter combine_dump = 1; 497918334Speter break; 498050615Sobrien#ifdef DELAY_SLOTS 498118334Speter case 'd': 498218334Speter dbr_sched_dump = 1; 498318334Speter break; 498450615Sobrien#endif 498518334Speter case 'f': 498618334Speter flow_dump = 1; 498718334Speter break; 498850615Sobrien case 'F': 498950615Sobrien addressof_dump = 1; 499050615Sobrien break; 499118334Speter case 'g': 499218334Speter global_reg_dump = 1; 499318334Speter break; 499450615Sobrien case 'G': 499550615Sobrien gcse_dump = 1; 499650615Sobrien break; 499718334Speter case 'j': 499818334Speter jump_opt_dump = 1; 499918334Speter break; 500018334Speter case 'J': 500118334Speter jump2_opt_dump = 1; 500218334Speter break; 500350615Sobrien#ifdef STACK_REGS 500450615Sobrien case 'k': 500550615Sobrien stack_reg_dump = 1; 500650615Sobrien break; 500750615Sobrien#endif 500818334Speter case 'l': 500918334Speter local_reg_dump = 1; 501018334Speter break; 501118334Speter case 'L': 501218334Speter loop_dump = 1; 501318334Speter break; 501418334Speter case 'm': 501518334Speter flag_print_mem = 1; 501618334Speter break; 501750615Sobrien#ifdef MACHINE_DEPENDENT_REORG 501850615Sobrien case 'M': 501950615Sobrien mach_dep_reorg_dump = 1; 502050615Sobrien break; 502150615Sobrien#endif 502218334Speter case 'p': 502318334Speter flag_print_asm_name = 1; 502418334Speter break; 502518334Speter case 'r': 502618334Speter rtl_dump = 1; 502718334Speter break; 502850615Sobrien case 'R': 502950615Sobrien sched2_dump = 1; 503050615Sobrien break; 503118334Speter case 's': 503218334Speter cse_dump = 1; 503318334Speter break; 503450615Sobrien case 'S': 503550615Sobrien sched_dump = 1; 503650615Sobrien break; 503718334Speter case 't': 503818334Speter cse2_dump = 1; 503918334Speter break; 504050615Sobrien case 'N': 504150615Sobrien regmove_dump = 1; 504218334Speter break; 504352558Sobrien case 'v': 504452558Sobrien graph_dump_format = vcg; 504552558Sobrien break; 504652558Sobrien case 'w': 504752558Sobrien flow2_dump = 1; 504852558Sobrien break; 504918334Speter case 'y': 505018334Speter set_yydebug (1); 505118334Speter break; 505218334Speter case 'x': 505318334Speter rtl_dump_and_exit = 1; 505418334Speter break; 505552558Sobrien case 'D': /* these are handled by the preprocessor */ 505652558Sobrien case 'I': 505752558Sobrien break; 505850615Sobrien default: 505950615Sobrien warning ("unrecognised gcc debugging option: %c", p[-1]); 506050615Sobrien break; 506118334Speter } 506218334Speter } 506318334Speter else if (str[0] == 'f') 506418334Speter { 506518334Speter register char *p = &str[1]; 506618334Speter int found = 0; 506718334Speter 506818334Speter /* Some kind of -f option. 506918334Speter P's value is the option sans `-f'. 507018334Speter Search for it in the table of options. */ 507118334Speter 507218334Speter for (j = 0; 507318334Speter !found && j < sizeof (f_options) / sizeof (f_options[0]); 507418334Speter j++) 507518334Speter { 507618334Speter if (!strcmp (p, f_options[j].string)) 507718334Speter { 507818334Speter *f_options[j].variable = f_options[j].on_value; 507918334Speter /* A goto here would be cleaner, 508018334Speter but breaks the vax pcc. */ 508118334Speter found = 1; 508218334Speter } 508318334Speter if (p[0] == 'n' && p[1] == 'o' && p[2] == '-' 508418334Speter && ! strcmp (p+3, f_options[j].string)) 508518334Speter { 508618334Speter *f_options[j].variable = ! f_options[j].on_value; 508718334Speter found = 1; 508818334Speter } 508918334Speter } 509018334Speter 509118334Speter if (found) 509218334Speter ; 509352558Sobrien else if (!strncmp (p, "inline-limit-", 13)) 509452558Sobrien inline_max_insns = 509552558Sobrien read_integral_parameter (p + 13, p - 2, inline_max_insns); 509650615Sobrien#ifdef HAIFA 509750615Sobrien#ifdef INSN_SCHEDULING 509850615Sobrien else if (!strncmp (p, "sched-verbose-",14)) 509950615Sobrien fix_sched_param("verbose",&p[14]); 510050615Sobrien#endif 510150615Sobrien#endif /* HAIFA */ 510218334Speter else if (!strncmp (p, "fixed-", 6)) 510318334Speter fix_register (&p[6], 1, 1); 510418334Speter else if (!strncmp (p, "call-used-", 10)) 510518334Speter fix_register (&p[10], 0, 1); 510618334Speter else if (!strncmp (p, "call-saved-", 11)) 510718334Speter fix_register (&p[11], 0, 0); 510818334Speter else 510918334Speter error ("Invalid option `%s'", argv[i]); 511018334Speter } 511118334Speter else if (str[0] == 'O') 511218334Speter { 511352558Sobrien /* Already been treated above. Do nothing. */ 511418334Speter } 511518334Speter else if (!strcmp (str, "pedantic")) 511618334Speter pedantic = 1; 511718334Speter else if (!strcmp (str, "pedantic-errors")) 511818334Speter flag_pedantic_errors = pedantic = 1; 511918334Speter else if (!strcmp (str, "quiet")) 512018334Speter quiet_flag = 1; 512118334Speter else if (!strcmp (str, "version")) 512218334Speter version_flag = 1; 512318334Speter else if (!strcmp (str, "w")) 512418334Speter inhibit_warnings = 1; 512518334Speter else if (!strcmp (str, "W")) 512618334Speter { 512718334Speter extra_warnings = 1; 512818334Speter /* We save the value of warn_uninitialized, since if they put 512918334Speter -Wuninitialized on the command line, we need to generate a 513018334Speter warning about not using it without also specifying -O. */ 513118334Speter if (warn_uninitialized != 1) 513218334Speter warn_uninitialized = 2; 513318334Speter } 513418334Speter else if (str[0] == 'W') 513518334Speter { 513618334Speter register char *p = &str[1]; 513718334Speter int found = 0; 513818334Speter 513918334Speter /* Some kind of -W option. 514018334Speter P's value is the option sans `-W'. 514118334Speter Search for it in the table of options. */ 514218334Speter 514318334Speter for (j = 0; 514418334Speter !found && j < sizeof (W_options) / sizeof (W_options[0]); 514518334Speter j++) 514618334Speter { 514718334Speter if (!strcmp (p, W_options[j].string)) 514818334Speter { 514918334Speter *W_options[j].variable = W_options[j].on_value; 515018334Speter /* A goto here would be cleaner, 515118334Speter but breaks the vax pcc. */ 515218334Speter found = 1; 515318334Speter } 515418334Speter if (p[0] == 'n' && p[1] == 'o' && p[2] == '-' 515518334Speter && ! strcmp (p+3, W_options[j].string)) 515618334Speter { 515718334Speter *W_options[j].variable = ! W_options[j].on_value; 515818334Speter found = 1; 515918334Speter } 516018334Speter } 516118334Speter 516218334Speter if (found) 516318334Speter ; 516418334Speter else if (!strncmp (p, "id-clash-", 9)) 516518334Speter { 516652558Sobrien const int id_clash_val 516752558Sobrien = read_integral_parameter (p + 9, p - 2, -1); 516852558Sobrien if (id_clash_val != -1) 516918334Speter { 517052558Sobrien id_clash_len = id_clash_val; 517152558Sobrien warn_id_clash = 1; 517218334Speter } 517318334Speter } 517418334Speter else if (!strncmp (p, "larger-than-", 12)) 517518334Speter { 517652558Sobrien const int larger_than_val 517752558Sobrien = read_integral_parameter (p + 12, p - 2, -1); 517852558Sobrien if (larger_than_val != -1) 517918334Speter { 518052558Sobrien larger_than_size = larger_than_val; 518152558Sobrien warn_larger_than = 1; 518218334Speter } 518318334Speter } 518418334Speter else 518518334Speter error ("Invalid option `%s'", argv[i]); 518618334Speter } 518718334Speter else if (!strcmp (str, "p")) 518818334Speter { 518950615Sobrien profile_flag = 1; 519018334Speter } 519118334Speter else if (!strcmp (str, "a")) 519218334Speter { 519318334Speter#if !defined (BLOCK_PROFILER) || !defined (FUNCTION_BLOCK_PROFILER) 519418334Speter warning ("`-a' option (basic block profile) not supported"); 519518334Speter#else 519650615Sobrien profile_block_flag = (profile_block_flag < 2) ? 1 : 3; 519718334Speter#endif 519818334Speter } 519950615Sobrien else if (!strcmp (str, "ax")) 520050615Sobrien { 520150615Sobrien#if !defined (FUNCTION_BLOCK_PROFILER_EXIT) || !defined (BLOCK_PROFILER) || !defined (FUNCTION_BLOCK_PROFILER) 520250615Sobrien warning ("`-ax' option (jump profiling) not supported"); 520350615Sobrien#else 520450615Sobrien profile_block_flag = (!profile_block_flag 520550615Sobrien || profile_block_flag == 2) ? 2 : 3; 520650615Sobrien#endif 520750615Sobrien } 520818334Speter else if (str[0] == 'g') 520918334Speter { 521018334Speter unsigned level; 521150615Sobrien /* A lot of code assumes write_symbols == NO_DEBUG if the 521250615Sobrien debugging level is 0 (thus -gstabs1 -gstabs0 would lose track 521350615Sobrien of what debugging type has been selected). This records the 521450615Sobrien selected type. It is an error to specify more than one 521550615Sobrien debugging type. */ 521650615Sobrien static enum debug_info_type selected_debug_type = NO_DEBUG; 521750615Sobrien /* Non-zero if debugging format has been explicitly set. 521850615Sobrien -g and -ggdb don't explicitly set the debugging format so 521950615Sobrien -gdwarf -g3 is equivalent to -gdwarf3. */ 522050615Sobrien static int type_explicitly_set_p = 0; 522150615Sobrien /* Indexed by enum debug_info_type. */ 522252558Sobrien static const char *debug_type_names[] = 522350615Sobrien { 522450615Sobrien "none", "stabs", "coff", "dwarf-1", "dwarf-2", "xcoff" 522550615Sobrien }; 522618334Speter 522752558Sobrien /* The maximum admissible debug level value. */ 522852558Sobrien static const unsigned max_debug_level = 3; 522952558Sobrien 523050615Sobrien /* Look up STR in the table. */ 523150615Sobrien for (da = debug_args; da->arg; da++) 523218334Speter { 523352558Sobrien const int da_len = strlen (da->arg); 523452558Sobrien 523552558Sobrien if (! strncmp (str, da->arg, da_len)) 523650615Sobrien { 523750615Sobrien enum debug_info_type type = da->debug_type; 523852558Sobrien const char *p = str + da_len; 523918334Speter 524050615Sobrien if (*p && (*p < '0' || *p > '9')) 524150615Sobrien continue; 524252558Sobrien 524352558Sobrien /* A debug flag without a level defaults to level 2. 524452558Sobrien Note we do not want to call read_integral_parameter 524552558Sobrien for that case since it will call atoi which 524652558Sobrien will return zero. 524752558Sobrien 524852558Sobrien ??? We may want to generalize the interface to 524952558Sobrien read_integral_parameter to better handle this case 525052558Sobrien if this case shows up often. */ 525150615Sobrien if (*p) 525252558Sobrien level = read_integral_parameter (p, 0, 525352558Sobrien max_debug_level + 1); 525452558Sobrien else 525552558Sobrien level = 2; 525652558Sobrien 525752558Sobrien if (da_len > 1 && *p && !strncmp (str, "gdwarf", da_len)) 525850615Sobrien { 525952558Sobrien error ("use -gdwarf -g%d for DWARF v1, level %d", 526052558Sobrien level, level); 526152558Sobrien if (level == 2) 526252558Sobrien error ("use -gdwarf-2 for DWARF v2"); 526350615Sobrien } 526452558Sobrien 526552558Sobrien if (level > max_debug_level) 526650615Sobrien { 526752558Sobrien warning ("ignoring option `%s' due to invalid debug level specification", 526852558Sobrien str - 1); 526952558Sobrien level = debug_info_level; 527050615Sobrien } 527150615Sobrien 527250615Sobrien if (type == NO_DEBUG) 527350615Sobrien { 527450615Sobrien type = PREFERRED_DEBUGGING_TYPE; 527552558Sobrien if (da_len > 1 && strncmp (str, "ggdb", da_len) == 0) 527650615Sobrien { 527750615Sobrien#if defined (DWARF2_DEBUGGING_INFO) && !defined (LINKER_DOES_NOT_WORK_WITH_DWARF2) 527850615Sobrien type = DWARF2_DEBUG; 527950615Sobrien#else 528018334Speter#ifdef DBX_DEBUGGING_INFO 528150615Sobrien type = DBX_DEBUG; 528250615Sobrien#endif 528350615Sobrien#endif 528450615Sobrien } 528550615Sobrien } 528618334Speter 528750615Sobrien if (type == NO_DEBUG) 528850615Sobrien warning ("`-%s' not supported by this configuration of GCC", 528950615Sobrien str); 529018334Speter 529150615Sobrien /* Does it conflict with an already selected type? */ 529250615Sobrien if (type_explicitly_set_p 529350615Sobrien /* -g/-ggdb don't conflict with anything */ 529450615Sobrien && da->debug_type != NO_DEBUG 529550615Sobrien && type != selected_debug_type) 529650615Sobrien warning ("`-%s' ignored, conflicts with `-g%s'", 529750615Sobrien str, debug_type_names[(int) selected_debug_type]); 529850615Sobrien else 529950615Sobrien { 530050615Sobrien /* If the format has already been set, -g/-ggdb 530150615Sobrien only change the debug level. */ 530250615Sobrien if (type_explicitly_set_p 530350615Sobrien && da->debug_type == NO_DEBUG) 530450615Sobrien ; /* don't change debugging type */ 530550615Sobrien else 530650615Sobrien { 530750615Sobrien selected_debug_type = type; 530850615Sobrien type_explicitly_set_p = da->debug_type != NO_DEBUG; 530950615Sobrien } 531050615Sobrien write_symbols = (level == 0 531150615Sobrien ? NO_DEBUG 531250615Sobrien : selected_debug_type); 531350615Sobrien use_gnu_debug_info_extensions = da->use_extensions_p; 531450615Sobrien debug_info_level = (enum debug_info_level) level; 531550615Sobrien } 531650615Sobrien break; 531750615Sobrien } 531850615Sobrien } 531950615Sobrien if (! da->arg) 532018334Speter warning ("`-%s' not supported by this configuration of GCC", 532118334Speter str); 532218334Speter } 532318334Speter else if (!strcmp (str, "o")) 532418334Speter { 532518334Speter asm_file_name = argv[++i]; 532618334Speter } 532718334Speter else if (str[0] == 'G') 532818334Speter { 532952558Sobrien const int g_switch_val = (str[1] != '\0') ? 533052558Sobrien read_integral_parameter(str + 1, 0, -1) : 533152558Sobrien read_integral_parameter(argv[++i], 0, -1); 533252558Sobrien 533352558Sobrien if (g_switch_val != -1) 533452558Sobrien { 533552558Sobrien g_switch_set = TRUE; 533652558Sobrien g_switch_value = g_switch_val; 533752558Sobrien } 533852558Sobrien else 533952558Sobrien { 534052558Sobrien error("Invalid option `-%s'",str); 534152558Sobrien } 534218334Speter } 534318334Speter else if (!strncmp (str, "aux-info", 8)) 534418334Speter { 534518334Speter flag_gen_aux_info = 1; 534618334Speter aux_info_file_name = (str[8] != '\0' ? str+8 : argv[++i]); 534718334Speter } 534850615Sobrien else if (!strcmp (str, "-help")) 534950615Sobrien { 535050615Sobrien display_help (); 535150615Sobrien exit (0); 535250615Sobrien } 535318334Speter else 535418334Speter error ("Invalid option `%s'", argv[i]); 535518334Speter } 535618334Speter else if (argv[i][0] == '+') 535718334Speter error ("Invalid option `%s'", argv[i]); 535818334Speter else 535918334Speter filename = argv[i]; 536018334Speter } 536118334Speter 536250615Sobrien /* Checker uses the frame pointer. */ 536350615Sobrien if (flag_check_memory_usage) 536450615Sobrien flag_omit_frame_pointer = 0; 536518334Speter 536618334Speter if (optimize == 0) 536718334Speter { 536818334Speter /* Inlining does not work if not optimizing, 536918334Speter so force it not to be done. */ 537018334Speter flag_no_inline = 1; 537118334Speter warn_inline = 0; 537218334Speter 537318334Speter /* The c_decode_option and lang_decode_option functions set 537418334Speter this to `2' if -Wall is used, so we can avoid giving out 537518334Speter lots of errors for people who don't realize what -Wall does. */ 537618334Speter if (warn_uninitialized == 1) 537718334Speter warning ("-Wuninitialized is not supported without -O"); 537818334Speter } 537918334Speter 538018334Speter#ifdef OVERRIDE_OPTIONS 538118334Speter /* Some machines may reject certain combinations of options. */ 538218334Speter OVERRIDE_OPTIONS; 538318334Speter#endif 538418334Speter 538550615Sobrien if (exceptions_via_longjmp == 2) 538650615Sobrien { 538750615Sobrien#ifdef DWARF2_UNWIND_INFO 538850615Sobrien exceptions_via_longjmp = ! DWARF2_UNWIND_INFO; 538950615Sobrien#else 539050615Sobrien exceptions_via_longjmp = 1; 539150615Sobrien#endif 539250615Sobrien } 539350615Sobrien 539450615Sobrien if (profile_block_flag == 3) 539550615Sobrien { 539650615Sobrien warning ("`-ax' and `-a' are conflicting options. `-a' ignored."); 539750615Sobrien profile_block_flag = 2; 539850615Sobrien } 539950615Sobrien 540018334Speter /* Unrolling all loops implies that standard loop unrolling must also 540118334Speter be done. */ 540218334Speter if (flag_unroll_all_loops) 540318334Speter flag_unroll_loops = 1; 540418334Speter /* Loop unrolling requires that strength_reduction be on also. Silently 540518334Speter turn on strength reduction here if it isn't already on. Also, the loop 540618334Speter unrolling code assumes that cse will be run after loop, so that must 540718334Speter be turned on also. */ 540818334Speter if (flag_unroll_loops) 540918334Speter { 541018334Speter flag_strength_reduce = 1; 541118334Speter flag_rerun_cse_after_loop = 1; 541218334Speter } 541318334Speter 541418334Speter /* Warn about options that are not supported on this machine. */ 541518334Speter#ifndef INSN_SCHEDULING 541618334Speter if (flag_schedule_insns || flag_schedule_insns_after_reload) 541718334Speter warning ("instruction scheduling not supported on this target machine"); 541818334Speter#endif 541918334Speter#ifndef DELAY_SLOTS 542018334Speter if (flag_delayed_branch) 542118334Speter warning ("this target machine does not have delayed branches"); 542218334Speter#endif 542318334Speter 542452558Sobrien user_label_prefix = USER_LABEL_PREFIX; 542552558Sobrien if (flag_leading_underscore != -1) 542652558Sobrien { 542752558Sobrien /* If the default prefix is more complicated than "" or "_", 542852558Sobrien issue a warning and ignore this option. */ 542952558Sobrien if (user_label_prefix[0] == 0 || 543052558Sobrien (user_label_prefix[0] == '_' && user_label_prefix[1] == 0)) 543152558Sobrien { 543252558Sobrien user_label_prefix = flag_leading_underscore ? "_" : ""; 543352558Sobrien } 543452558Sobrien else 543552558Sobrien warning ("-f%sleading-underscore not supported on this target machine", 543652558Sobrien flag_leading_underscore ? "" : "no-"); 543752558Sobrien } 543852558Sobrien 543918334Speter /* If we are in verbose mode, write out the version and maybe all the 544018334Speter option flags in use. */ 544118334Speter if (version_flag) 544218334Speter { 544350615Sobrien print_version (stderr, ""); 544418334Speter if (! quiet_flag) 544550615Sobrien print_switch_values (stderr, 0, MAX_LINE, "", " ", "\n"); 544618334Speter } 544718334Speter 544818334Speter compile_file (filename); 544918334Speter 545052558Sobrien#if !defined(OS2) && !defined(VMS) && (!defined(_WIN32) || defined (__CYGWIN__)) && !defined(__INTERIX) 545118334Speter if (flag_print_mem) 545218334Speter { 545318334Speter char *lim = (char *) sbrk (0); 545418334Speter 545552558Sobrien notice ("Data size %ld.\n", (long) (lim - (char *) &environ)); 545618334Speter fflush (stderr); 545718334Speter 545850615Sobrien#ifndef __MSDOS__ 545918334Speter#ifdef USG 546018334Speter system ("ps -l 1>&2"); 546118334Speter#else /* not USG */ 546218334Speter system ("ps v"); 546318334Speter#endif /* not USG */ 546450615Sobrien#endif 546518334Speter } 546652558Sobrien#endif /* ! OS2 && ! VMS && (! _WIN32 || CYGWIN) && ! __INTERIX */ 546718334Speter 546818334Speter if (errorcount) 546918334Speter exit (FATAL_EXIT_CODE); 547018334Speter if (sorrycount) 547118334Speter exit (FATAL_EXIT_CODE); 547218334Speter exit (SUCCESS_EXIT_CODE); 547318334Speter return 0; 547418334Speter} 547518334Speter 547618334Speter/* Decode -m switches. */ 547718334Speter/* Decode the switch -mNAME. */ 547818334Speter 547952558Sobrienstatic void 548018334Speterset_target_switch (name) 548152558Sobrien const char *name; 548218334Speter{ 548350615Sobrien register size_t j; 548452558Sobrien int valid_target_option = 0; 548518334Speter 548618334Speter for (j = 0; j < sizeof target_switches / sizeof target_switches[0]; j++) 548718334Speter if (!strcmp (target_switches[j].name, name)) 548818334Speter { 548918334Speter if (target_switches[j].value < 0) 549018334Speter target_flags &= ~-target_switches[j].value; 549118334Speter else 549218334Speter target_flags |= target_switches[j].value; 549352558Sobrien valid_target_option = 1; 549418334Speter } 549518334Speter 549618334Speter#ifdef TARGET_OPTIONS 549752558Sobrien if (!valid_target_option) 549818334Speter for (j = 0; j < sizeof target_options / sizeof target_options[0]; j++) 549918334Speter { 550018334Speter int len = strlen (target_options[j].prefix); 550118334Speter if (!strncmp (target_options[j].prefix, name, len)) 550218334Speter { 550318334Speter *target_options[j].variable = name + len; 550452558Sobrien valid_target_option = 1; 550518334Speter } 550618334Speter } 550718334Speter#endif 550818334Speter 550952558Sobrien if (!valid_target_option) 551018334Speter error ("Invalid option `%s'", name); 551118334Speter} 551218334Speter 551350615Sobrien/* Print version information to FILE. 551450615Sobrien Each line begins with INDENT (for the case where FILE is the 551550615Sobrien assembler output file). */ 551618334Speter 551752558Sobrienstatic void 551850615Sobrienprint_version (file, indent) 551950615Sobrien FILE *file; 552052558Sobrien const char *indent; 552150615Sobrien{ 552250615Sobrien#ifndef __VERSION__ 552352558Sobrien#define __VERSION__ "[?]" 552450615Sobrien#endif 552552558Sobrien fnotice (file, 552652558Sobrien#ifdef __GNUC__ 552752558Sobrien "%s%s%s version %s (%s) compiled by GNU C version %s.\n" 552850615Sobrien#else 552952558Sobrien "%s%s%s version %s (%s) compiled by CC.\n" 553050615Sobrien#endif 553152558Sobrien , indent, *indent != 0 ? " " : "", 553252558Sobrien language_string, version_string, TARGET_NAME, __VERSION__); 553350615Sobrien} 553418334Speter 553550615Sobrien/* Print an option value and return the adjusted position in the line. 553650615Sobrien ??? We don't handle error returns from fprintf (disk full); presumably 553750615Sobrien other code will catch a disk full though. */ 553818334Speter 553952558Sobrienstatic int 554050615Sobrienprint_single_switch (file, pos, max, indent, sep, term, type, name) 554150615Sobrien FILE *file; 554250615Sobrien int pos, max; 554352558Sobrien const char *indent, *sep, *term, *type, *name; 554418334Speter{ 554550615Sobrien /* The ultrix fprintf returns 0 on success, so compute the result we want 554650615Sobrien here since we need it for the following test. */ 554750615Sobrien int len = strlen (sep) + strlen (type) + strlen (name); 554818334Speter 554950615Sobrien if (pos != 0 555050615Sobrien && pos + len > max) 555118334Speter { 555250615Sobrien fprintf (file, "%s", term); 555350615Sobrien pos = 0; 555418334Speter } 555550615Sobrien if (pos == 0) 555650615Sobrien { 555750615Sobrien fprintf (file, "%s", indent); 555850615Sobrien pos = strlen (indent); 555950615Sobrien } 556050615Sobrien fprintf (file, "%s%s%s", sep, type, name); 556150615Sobrien pos += len; 556250615Sobrien return pos; 556318334Speter} 556418334Speter 556550615Sobrien/* Print active target switches to FILE. 556650615Sobrien POS is the current cursor position and MAX is the size of a "line". 556750615Sobrien Each line begins with INDENT and ends with TERM. 556850615Sobrien Each switch is separated from the next by SEP. */ 556918334Speter 557052558Sobrienstatic void 557150615Sobrienprint_switch_values (file, pos, max, indent, sep, term) 557250615Sobrien FILE *file; 557350615Sobrien int pos, max; 557452558Sobrien const char *indent, *sep, *term; 557518334Speter{ 557650615Sobrien size_t j; 557750615Sobrien char **p; 557818334Speter 557950615Sobrien /* Print the options as passed. */ 558018334Speter 558150615Sobrien pos = print_single_switch (file, pos, max, indent, *indent ? " " : "", term, 558252558Sobrien _("options passed: "), ""); 558350615Sobrien 558450615Sobrien for (p = &save_argv[1]; *p != NULL; p++) 558550615Sobrien if (**p == '-') 558650615Sobrien { 558750615Sobrien /* Ignore these. */ 558850615Sobrien if (strcmp (*p, "-o") == 0) 558950615Sobrien { 559050615Sobrien if (p[1] != NULL) 559150615Sobrien p++; 559250615Sobrien continue; 559350615Sobrien } 559450615Sobrien if (strcmp (*p, "-quiet") == 0) 559550615Sobrien continue; 559650615Sobrien if (strcmp (*p, "-version") == 0) 559750615Sobrien continue; 559850615Sobrien if ((*p)[1] == 'd') 559950615Sobrien continue; 560050615Sobrien 560150615Sobrien pos = print_single_switch (file, pos, max, indent, sep, term, *p, ""); 560250615Sobrien } 560350615Sobrien if (pos > 0) 560450615Sobrien fprintf (file, "%s", term); 560550615Sobrien 560650615Sobrien /* Print the -f and -m options that have been enabled. 560750615Sobrien We don't handle language specific options but printing argv 560850615Sobrien should suffice. */ 560950615Sobrien 561050615Sobrien pos = print_single_switch (file, 0, max, indent, *indent ? " " : "", term, 561152558Sobrien _("options enabled: "), ""); 561250615Sobrien 561318334Speter for (j = 0; j < sizeof f_options / sizeof f_options[0]; j++) 561418334Speter if (*f_options[j].variable == f_options[j].on_value) 561550615Sobrien pos = print_single_switch (file, pos, max, indent, sep, term, 561650615Sobrien "-f", f_options[j].string); 561718334Speter 561850615Sobrien /* Print target specific options. */ 561918334Speter 562018334Speter for (j = 0; j < sizeof target_switches / sizeof target_switches[0]; j++) 562118334Speter if (target_switches[j].name[0] != '\0' 562218334Speter && target_switches[j].value > 0 562318334Speter && ((target_switches[j].value & target_flags) 562418334Speter == target_switches[j].value)) 562550615Sobrien { 562650615Sobrien pos = print_single_switch (file, pos, max, indent, sep, term, 562750615Sobrien "-m", target_switches[j].name); 562850615Sobrien } 562918334Speter 563050615Sobrien#ifdef TARGET_OPTIONS 563150615Sobrien for (j = 0; j < sizeof target_options / sizeof target_options[0]; j++) 563250615Sobrien if (*target_options[j].variable != NULL) 563350615Sobrien { 563450615Sobrien char prefix[256]; 563550615Sobrien sprintf (prefix, "-m%s", target_options[j].prefix); 563650615Sobrien pos = print_single_switch (file, pos, max, indent, sep, term, 563750615Sobrien prefix, *target_options[j].variable); 563850615Sobrien } 563950615Sobrien#endif 564050615Sobrien 564150615Sobrien fprintf (file, "%s", term); 564218334Speter} 564350615Sobrien 564450615Sobrien/* Record the beginning of a new source file, named FILENAME. */ 564550615Sobrien 564650615Sobrienvoid 564750615Sobriendebug_start_source_file (filename) 564852558Sobrien register char *filename ATTRIBUTE_UNUSED; 564950615Sobrien{ 565050615Sobrien#ifdef DBX_DEBUGGING_INFO 565150615Sobrien if (write_symbols == DBX_DEBUG) 565250615Sobrien dbxout_start_new_source_file (filename); 565350615Sobrien#endif 565450615Sobrien#ifdef DWARF_DEBUGGING_INFO 565550615Sobrien if (debug_info_level == DINFO_LEVEL_VERBOSE 565650615Sobrien && write_symbols == DWARF_DEBUG) 565750615Sobrien dwarfout_start_new_source_file (filename); 565850615Sobrien#endif /* DWARF_DEBUGGING_INFO */ 565950615Sobrien#ifdef DWARF2_DEBUGGING_INFO 566050615Sobrien if (debug_info_level == DINFO_LEVEL_VERBOSE 566150615Sobrien && write_symbols == DWARF2_DEBUG) 566250615Sobrien dwarf2out_start_source_file (filename); 566350615Sobrien#endif /* DWARF2_DEBUGGING_INFO */ 566450615Sobrien#ifdef SDB_DEBUGGING_INFO 566550615Sobrien if (write_symbols == SDB_DEBUG) 566650615Sobrien sdbout_start_new_source_file (filename); 566750615Sobrien#endif 566850615Sobrien} 566950615Sobrien 567050615Sobrien/* Record the resumption of a source file. LINENO is the line number in 567150615Sobrien the source file we are returning to. */ 567250615Sobrien 567350615Sobrienvoid 567450615Sobriendebug_end_source_file (lineno) 567552558Sobrien register unsigned lineno ATTRIBUTE_UNUSED; 567650615Sobrien{ 567750615Sobrien#ifdef DBX_DEBUGGING_INFO 567850615Sobrien if (write_symbols == DBX_DEBUG) 567950615Sobrien dbxout_resume_previous_source_file (); 568050615Sobrien#endif 568150615Sobrien#ifdef DWARF_DEBUGGING_INFO 568250615Sobrien if (debug_info_level == DINFO_LEVEL_VERBOSE 568350615Sobrien && write_symbols == DWARF_DEBUG) 568450615Sobrien dwarfout_resume_previous_source_file (lineno); 568550615Sobrien#endif /* DWARF_DEBUGGING_INFO */ 568650615Sobrien#ifdef DWARF2_DEBUGGING_INFO 568750615Sobrien if (debug_info_level == DINFO_LEVEL_VERBOSE 568850615Sobrien && write_symbols == DWARF2_DEBUG) 568950615Sobrien dwarf2out_end_source_file (); 569050615Sobrien#endif /* DWARF2_DEBUGGING_INFO */ 569150615Sobrien#ifdef SDB_DEBUGGING_INFO 569250615Sobrien if (write_symbols == SDB_DEBUG) 569350615Sobrien sdbout_resume_previous_source_file (); 569450615Sobrien#endif 569550615Sobrien} 569650615Sobrien 569750615Sobrien/* Called from check_newline in c-parse.y. The `buffer' parameter contains 569850615Sobrien the tail part of the directive line, i.e. the part which is past the 569950615Sobrien initial whitespace, #, whitespace, directive-name, whitespace part. */ 570050615Sobrien 570150615Sobrienvoid 570250615Sobriendebug_define (lineno, buffer) 570352558Sobrien register unsigned lineno ATTRIBUTE_UNUSED; 570452558Sobrien register char *buffer ATTRIBUTE_UNUSED; 570550615Sobrien{ 570650615Sobrien#ifdef DWARF_DEBUGGING_INFO 570750615Sobrien if (debug_info_level == DINFO_LEVEL_VERBOSE 570850615Sobrien && write_symbols == DWARF_DEBUG) 570950615Sobrien dwarfout_define (lineno, buffer); 571050615Sobrien#endif /* DWARF_DEBUGGING_INFO */ 571150615Sobrien#ifdef DWARF2_DEBUGGING_INFO 571250615Sobrien if (debug_info_level == DINFO_LEVEL_VERBOSE 571350615Sobrien && write_symbols == DWARF2_DEBUG) 571450615Sobrien dwarf2out_define (lineno, buffer); 571550615Sobrien#endif /* DWARF2_DEBUGGING_INFO */ 571650615Sobrien} 571750615Sobrien 571850615Sobrien/* Called from check_newline in c-parse.y. The `buffer' parameter contains 571950615Sobrien the tail part of the directive line, i.e. the part which is past the 572050615Sobrien initial whitespace, #, whitespace, directive-name, whitespace part. */ 572150615Sobrien 572250615Sobrienvoid 572350615Sobriendebug_undef (lineno, buffer) 572452558Sobrien register unsigned lineno ATTRIBUTE_UNUSED; 572552558Sobrien register char *buffer ATTRIBUTE_UNUSED; 572650615Sobrien{ 572750615Sobrien#ifdef DWARF_DEBUGGING_INFO 572850615Sobrien if (debug_info_level == DINFO_LEVEL_VERBOSE 572950615Sobrien && write_symbols == DWARF_DEBUG) 573050615Sobrien dwarfout_undef (lineno, buffer); 573150615Sobrien#endif /* DWARF_DEBUGGING_INFO */ 573250615Sobrien#ifdef DWARF2_DEBUGGING_INFO 573350615Sobrien if (debug_info_level == DINFO_LEVEL_VERBOSE 573450615Sobrien && write_symbols == DWARF2_DEBUG) 573550615Sobrien dwarf2out_undef (lineno, buffer); 573650615Sobrien#endif /* DWARF2_DEBUGGING_INFO */ 573750615Sobrien} 5738