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