#include "config.h"
#include "system.h"
#include "intl.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "ggc.h"
#include "output.h"
#include "langhooks.h"
#include "opts.h"
#include "options.h"
#include "flags.h"
#include "toplev.h"
#include "params.h"
#include "diagnostic.h"
#include "tm_p.h"
#include "insn-attr.h"
#include "target.h"
#include "hashtab.h"
unsigned HOST_WIDE_INT g_switch_value;
bool g_switch_set;
bool exit_after_options;
bool extra_warnings;
bool warn_larger_than;
HOST_WIDE_INT larger_than_size;
int warn_strict_aliasing;
static bool maybe_warn_unused_parameter;
enum debug_info_type write_symbols = NO_DEBUG;
enum debug_info_level debug_info_level = DINFO_LEVEL_NONE;
bool use_gnu_debug_info_extensions;
enum symbol_visibility default_visibility = VISIBILITY_DEFAULT;
bool no_unit_at_a_time_default;
struct visibility_flags visibility_options;
static unsigned int columns = 80;
static const char undocumented_msg[] = N_("This switch lacks documentation");
static bool profile_arc_flag_set, flag_profile_values_set;
static bool flag_unroll_loops_set, flag_tracer_set;
static bool flag_value_profile_transformations_set;
bool flag_speculative_prefetching_set;
static bool flag_peel_loops_set, flag_branch_probabilities_set;
const char **in_fnames;
unsigned num_in_fnames;
static size_t find_opt (const char *, int);
static int common_handle_option (size_t scode, const char *arg, int value);
static void handle_param (const char *);
static void set_Wextra (int);
static unsigned int handle_option (const char **argv, unsigned int lang_mask);
static char *write_langs (unsigned int lang_mask);
static void complain_wrong_lang (const char *, const struct cl_option *,
unsigned int lang_mask);
static void handle_options (unsigned int, const char **, unsigned int);
static void wrap_help (const char *help, const char *item, unsigned int);
static void print_help (void);
static void print_param_help (void);
static void print_filtered_help (unsigned int flag);
static unsigned int print_switch (const char *text, unsigned int indent);
static void set_debug_level (enum debug_info_type type, int extended,
const char *arg);
static size_t
find_opt (const char *input, int lang_mask)
{
size_t mn, mx, md, opt_len;
size_t match_wrong_lang;
int comp;
mn = 0;
mx = cl_options_count;
while (mx - mn > 1)
{
md = (mn + mx) / 2;
opt_len = cl_options[md].opt_len;
comp = strncmp (input, cl_options[md].opt_text + 1, opt_len);
if (comp < 0)
mx = md;
else
mn = md;
}
match_wrong_lang = cl_options_count;
do
{
const struct cl_option *opt = &cl_options[mn];
if (!strncmp (input, opt->opt_text + 1, opt->opt_len)
&& (input[opt->opt_len] == '\0' || (opt->flags & CL_JOINED)))
{
if (opt->flags & lang_mask)
return mn;
if (match_wrong_lang == cl_options_count)
match_wrong_lang = mn;
}
mn = opt->back_chain;
}
while (mn != cl_options_count);
return match_wrong_lang;
}
static int
integral_argument (const char *arg)
{
const char *p = arg;
while (*p && ISDIGIT (*p))
p++;
if (*p == '\0')
return atoi (arg);
return -1;
}
static char *
write_langs (unsigned int mask)
{
unsigned int n = 0, len = 0;
const char *lang_name;
char *result;
for (n = 0; (lang_name = lang_names[n]) != 0; n++)
if (mask & (1U << n))
len += strlen (lang_name) + 1;
result = xmalloc (len);
len = 0;
for (n = 0; (lang_name = lang_names[n]) != 0; n++)
if (mask & (1U << n))
{
if (len)
result[len++] = '/';
strcpy (result + len, lang_name);
len += strlen (lang_name);
}
result[len] = 0;
return result;
}
static void
complain_wrong_lang (const char *text, const struct cl_option *option,
unsigned int lang_mask)
{
char *ok_langs, *bad_lang;
ok_langs = write_langs (option->flags);
bad_lang = write_langs (lang_mask);
warning ("command line option \"%s\" is valid for %s but not for %s",
text, ok_langs, bad_lang);
free (ok_langs);
free (bad_lang);
}
static unsigned int
handle_option (const char **argv, unsigned int lang_mask)
{
size_t opt_index;
const char *opt, *arg = 0;
char *dup = 0;
int value = 1;
unsigned int result = 0;
const struct cl_option *option;
opt = argv[0];
if ((opt[1] == 'W' || opt[1] == 'f')
&& opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
{
size_t len = strlen (opt) - 3;
dup = xmalloc (len + 1);
dup[0] = '-';
dup[1] = opt[1];
memcpy (dup + 2, opt + 5, len - 2 + 1);
opt = dup;
value = 0;
}
opt_index = find_opt (opt + 1, lang_mask | CL_COMMON | CL_TARGET);
if (opt_index == cl_options_count)
goto done;
option = &cl_options[opt_index];
if (!value && (option->flags & CL_REJECT_NEGATIVE))
goto done;
result = 1;
if (option->flags & CL_JOINED)
{
arg = argv[0] + cl_options[opt_index].opt_len + 1;
if (!value)
arg += strlen ("no-");
if (*arg == '\0' && !(option->flags & CL_MISSING_OK))
{
if (option->flags & CL_SEPARATE)
{
arg = argv[1];
result = 2;
}
else
arg = NULL;
}
}
else if (option->flags & CL_SEPARATE)
{
arg = argv[1];
result = 2;
}
if (!(option->flags & (lang_mask | CL_COMMON | CL_TARGET)))
{
complain_wrong_lang (argv[0], option, lang_mask);
goto done;
}
else if ((option->flags & CL_TARGET)
&& (option->flags & CL_LANG_ALL)
&& !(option->flags & lang_mask))
{
complain_wrong_lang (argv[0], option, lang_mask);
goto done;
}
if (arg == NULL && (option->flags & (CL_JOINED | CL_SEPARATE)))
{
if (!lang_hooks.missing_argument (opt, opt_index))
error ("missing argument to \"%s\"", opt);
goto done;
}
if (arg && (option->flags & CL_UINTEGER))
{
value = integral_argument (arg);
if (value == -1)
{
error ("argument to \"%s\" should be a non-negative integer",
option->opt_text);
goto done;
}
}
if (option->flag_var)
{
if (option->has_set_value)
{
if (value)
*option->flag_var = option->set_value;
else
*option->flag_var = !option->set_value;
}
else
*option->flag_var = value;
}
else if (option->access_flag)
{
if (option->has_set_value)
{
if (value)
(option->access_flag) (option->set_value, 1);
else
(option->access_flag) (!option->set_value, 1);
}
else
(option->access_flag) (value, 1);
}
if (option->flags & lang_mask)
if (lang_hooks.handle_option (opt_index, arg, value) == 0)
result = 0;
if (result && (option->flags & CL_COMMON))
if (common_handle_option (opt_index, arg, value) == 0)
result = 0;
done:
if (dup)
free (dup);
return result;
}
static void
add_input_filename (const char *filename)
{
num_in_fnames++;
in_fnames = xrealloc (in_fnames, num_in_fnames * sizeof (in_fnames[0]));
in_fnames[num_in_fnames - 1] = filename;
}
static void
handle_options (unsigned int argc, const char **argv, unsigned int lang_mask)
{
unsigned int n, i;
for (i = 1; i < argc; i += n)
{
const char *opt = argv[i];
if (opt[0] != '-' || opt[1] == '\0')
{
if (main_input_filename == NULL)
main_input_filename = opt;
add_input_filename (opt);
n = 1;
continue;
}
n = handle_option (argv + i, lang_mask);
if (!n)
{
n = 1;
error ("unrecognized command line option \"%s\"", opt);
}
}
}
void set_flags_from_O (unsigned int cmdline)
{
int save_optimize_size = optimize_size;
int save_optimize = optimize;
cl_pf_opts = cl_pf_opts_raw;
optimize = save_optimize;
optimize_size = save_optimize_size;
if (!optimize)
{
if (cmdline)
flag_merge_constants = 0;
flag_clone_structors = 1;
}
if (optimize >= 1)
{
flag_defer_pop = 1;
#ifdef DELAY_SLOTS
flag_delayed_branch = 1;
#endif
#ifdef CAN_DEBUG_WITHOUT_FP
flag_omit_frame_pointer = 1;
#endif
flag_guess_branch_prob = 1;
flag_cprop_registers = 1;
flag_loop_optimize = 1;
flag_if_conversion = 1;
flag_if_conversion2 = 1;
flag_tree_ccp = 1;
flag_tree_dce = 1;
flag_tree_dom = 1;
flag_tree_dse = 1;
flag_tree_loop_im = 1;
flag_ivopts = 1;
flag_tree_vectorize = 0;
flag_tree_loop_linear = 0;
flag_tree_ter = 1;
flag_tree_live_range_split = 1;
flag_tree_sra = 1;
flag_tree_copyrename = 1;
flag_tree_fre = 1;
if (!no_unit_at_a_time_default)
flag_unit_at_a_time = 1;
if (!optimize_size)
{
flag_tree_ch = 1;
}
}
if (optimize >= 2)
{
flag_thread_jumps = 1;
flag_crossjumping = 1;
flag_optimize_sibling_calls = 1;
flag_cse_follow_jumps = 1;
flag_cse_skip_blocks = 1;
flag_gcse = 1;
flag_expensive_optimizations = 1;
flag_strength_reduce = 1;
flag_rerun_cse_after_loop = 1;
flag_rerun_loop_opt = 1;
flag_caller_saves = 1;
flag_peephole2 = 1;
#ifdef INSN_SCHEDULING
flag_schedule_insns = 1;
flag_schedule_insns_after_reload = 1;
#endif
flag_regmove = 1;
flag_delete_null_pointer_checks = 1;
flag_reorder_blocks = 1;
if (cmdline)
{
flag_strict_aliasing = 1;
flag_reorder_functions = 1;
}
if (!optimize_size)
{
flag_tree_pre = 1;
}
}
if (optimize >= 3)
{
if (cmdline)
flag_inline_functions = 1;
flag_unswitch_loops = 1;
flag_gcse_after_reload = 1;
}
if (optimize < 2 || optimize_size)
{
align_loops = 1;
align_jumps = 1;
align_labels = 1;
if (cmdline)
align_functions = 1;
flag_reorder_blocks = 0;
flag_reorder_blocks_and_partition = 0;
}
if (optimize_size)
{
if (cmdline)
{
int estimated_insns = (!strcmp (lang_hooks.name, "GNU C")
|| !strcmp (lang_hooks.name, "GNU Objective-C"))
? 450 : 30;
set_param_value ("max-inline-insns-single", estimated_insns);
set_param_value ("max-inline-insns-auto", 30);
flag_inline_functions = 1;
set_param_value ("min-crossjump-insns", 1);
}
}
}
void
decode_options (unsigned int argc, const char **argv)
{
unsigned int i, lang_mask;
unsigned int optimize_size_z = 0;
int saved_flag_strict_aliasing;
lang_mask = lang_hooks.init_options (argc, argv);
lang_hooks.initialize_diagnostics (global_dc);
cl_pf_opts_raw = cl_pf_opts;
for (i = 1; i < argc; i++)
{
if (!strcmp (argv[i], "-O"))
{
optimize = 1;
optimize_size = 0;
}
else if (argv[i][0] == '-' && argv[i][1] == 'O')
{
const char *p = &argv[i][2];
if ((p[0] == 's' || p[0] == 'z') && (p[1] == 0))
{
optimize_size = 1;
optimize_size_z = (p[0] == 'z');
optimize = 2;
}
else
{
const int optimize_val = read_integral_parameter (p, p - 2, -1);
if (optimize_val != -1)
{
optimize = optimize_val;
optimize_size = 0;
}
}
}
else if (argv[i][0] == '-' && argv[i][1] == 'f')
{
const char *p = &argv[i][2];
if (!strcmp(p, "ast"))
flag_fast = 1;
else if (!strcmp(p, "astf"))
flag_fastf = 1;
else if (!strcmp(p, "astcp"))
flag_fastcp = 1;
}
}
if (flag_fast || flag_fastf || flag_fastcp )
{
optimize = 3;
optimize_size = 0;
if (flag_fast || flag_fastcp)
flag_no_common = 1;
}
set_flags_from_O (true);
flag_signed_char = DEFAULT_SIGNED_CHAR;
flag_short_enums = 2;
target_flags = 0;
set_target_switch ("");
#ifdef TARGET_UNWIND_INFO
flag_unwind_tables = TARGET_UNWIND_INFO;
#endif
#ifdef OPTIMIZATION_OPTIONS
OPTIMIZATION_OPTIONS (optimize, optimize_size);
#endif
#ifdef TARGET_ARM
if (optimize_size && !optimize_size_z)
{
set_param_value ("max-inline-insns-single", 15);
set_param_value ("max-inline-insns-auto", 15);
}
#endif
saved_flag_strict_aliasing = flag_strict_aliasing;
flag_strict_aliasing = 9;
handle_options (argc, argv, lang_mask);
if (flag_pie)
flag_pic = flag_pie;
if (flag_pic && !flag_pie)
flag_shlib = 1;
if (flag_no_inline == 2)
flag_no_inline = 0;
else
flag_really_no_inline = flag_no_inline;
if (optimize == 0)
{
flag_no_inline = 1;
warn_inline = 0;
if (warn_uninitialized == 1)
warning ("-Wuninitialized is not supported without -O");
}
if (flag_really_no_inline == 2)
flag_really_no_inline = flag_no_inline;
if (flag_exceptions && flag_reorder_blocks_and_partition)
{
warning
("-freorder-blocks-and-partition does not work with exceptions");
flag_reorder_blocks_and_partition = 0;
flag_reorder_blocks = 1;
}
if (flag_reorder_blocks_and_partition && write_symbols == DWARF2_DEBUG)
{
warning
("-freorder-blocks-and-partition does not work with -g (currently)");
flag_reorder_blocks_and_partition = 0;
flag_reorder_blocks = 1;
}
if (optimize >= 2 && flag_tree_vectorize)
{
if (flag_strict_aliasing == 0)
warning
("-ftree-vectorize enables strict aliasing. -fno-strict-aliasing is ignored when Auto Vectorization is used.");
flag_strict_aliasing = 1;
}
else
if (flag_strict_aliasing == 9)
flag_strict_aliasing = saved_flag_strict_aliasing;
if (!optimize_size_z)
optimize_size = 0;
}
static int
common_handle_option (size_t scode, const char *arg, int value)
{
enum opt_code code = (enum opt_code) scode;
switch (code)
{
case OPT_arch:
break;
case OPT__help:
print_help ();
exit_after_options = true;
break;
case OPT__param:
handle_param (arg);
break;
case OPT__target_help:
display_target_options ();
exit_after_options = true;
break;
case OPT__version:
print_version (stderr, "");
exit_after_options = true;
break;
case OPT_G:
g_switch_value = value;
g_switch_set = true;
break;
case OPT_O:
case OPT_Os:
break;
case OPT_W:
set_Wextra (value);
break;
case OPT_Wextra:
set_Wextra (value);
break;
case OPT_Wlarger_than_:
larger_than_size = value;
warn_larger_than = value != -1;
break;
case OPT_Wstrict_aliasing:
case OPT_Wstrict_aliasing_:
warn_strict_aliasing = value;
break;
case OPT_Wunused:
set_Wunused (value);
break;
case OPT_aux_info:
case OPT_aux_info_:
aux_info_file_name = arg;
flag_gen_aux_info = 1;
break;
case OPT_auxbase:
aux_base_name = arg;
break;
case OPT_auxbase_strip:
{
char *tmp = xstrdup (arg);
strip_off_ending (tmp, strlen (tmp));
if (tmp[0])
aux_base_name = tmp;
}
break;
case OPT_d:
decode_d_option (arg);
break;
case OPT_dumpbase:
dump_base_name = arg;
break;
case OPT_falign_jumps_max_skip_:
align_jumps_max_skip = value;
break;
case OPT_falign_loops_max_skip_:
align_loops_max_skip = value;
break;
case OPT_fpredictive_compilation:
predictive_compilation = 0;
break;
case OPT_fpredictive_compilation_:
{
char* buf = xmalloc (strlen(arg) + 1);
sprintf (buf, "%d", value);
if (strcmp(buf, arg))
{
error ("argument to \"-fpredictive-compilation=\" should be a valid non-negative integer instead of \"%s\"", arg);
value = 0;
}
free(buf);
predictive_compilation = value;
break;
}
case OPT_fbranch_probabilities:
flag_branch_probabilities_set = true;
break;
case OPT_fcall_used_:
fix_register (arg, 0, 1);
break;
case OPT_fcall_saved_:
fix_register (arg, 0, 0);
break;
case OPT_fdiagnostics_show_location_:
if (!strcmp (arg, "once"))
diagnostic_prefixing_rule (global_dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
else if (!strcmp (arg, "every-line"))
diagnostic_prefixing_rule (global_dc)
= DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
else
return 0;
break;
case OPT_fdump_:
if (!dump_switch_p (arg))
return 0;
break;
case OPT_ffast_math:
set_fast_math_flags (value);
break;
case OPT_ffixed_:
fix_register (arg, 1, 1);
break;
case OPT_finline_limit_:
case OPT_finline_limit_eq:
set_param_value ("max-inline-insns-single", value / 2);
set_param_value ("max-inline-insns-auto", value / 2);
break;
case OPT_fmessage_length_:
pp_set_line_maximum_length (global_dc->printer, value);
break;
case OPT_fpack_struct_:
if (value <= 0 || (value & (value - 1)) || value > 16)
error("structure alignment must be a small power of two, not %d", value);
else
{
initial_max_fld_align = value;
maximum_field_alignment = value * BITS_PER_UNIT;
}
break;
case OPT_fpeel_loops:
flag_peel_loops_set = true;
break;
case OPT_fprofile_arcs:
profile_arc_flag_set = true;
break;
case OPT_fuse_profile:
case OPT_fprofile_use:
if (!flag_branch_probabilities_set)
flag_branch_probabilities = value;
if (!flag_profile_values_set)
flag_profile_values = value;
if (!flag_unroll_loops_set)
flag_unroll_loops = value;
if (!flag_peel_loops_set)
flag_peel_loops = value;
if (!flag_tracer_set)
flag_tracer = value;
if (!flag_value_profile_transformations_set)
flag_value_profile_transformations = value;
#ifdef HAVE_prefetch
if (0 && !flag_speculative_prefetching_set)
flag_speculative_prefetching = value;
#endif
break;
case OPT_fcreate_profile:
case OPT_fprofile_generate:
if (!profile_arc_flag_set)
profile_arc_flag = value;
if (!flag_profile_values_set)
flag_profile_values = value;
if (!flag_value_profile_transformations_set)
flag_value_profile_transformations = value;
if (!flag_unroll_loops_set)
flag_unroll_loops = value;
#ifdef HAVE_prefetch
if (0 && !flag_speculative_prefetching_set)
flag_speculative_prefetching = value;
#endif
break;
case OPT_fprofile_values:
flag_profile_values_set = true;
break;
case OPT_fvisibility_:
{
if (!strcmp(arg, "default"))
default_visibility = VISIBILITY_DEFAULT;
else if (!strcmp(arg, "internal"))
default_visibility = VISIBILITY_INTERNAL;
else if (!strcmp(arg, "hidden"))
default_visibility = VISIBILITY_HIDDEN;
else if (!strcmp(arg, "protected"))
default_visibility = VISIBILITY_PROTECTED;
else
error ("unrecognised visibility value \"%s\"", arg);
}
break;
case OPT_fvpt:
flag_value_profile_transformations_set = true;
break;
case OPT_fspeculative_prefetching:
flag_speculative_prefetching_set = true;
break;
case OPT_frandom_seed:
if (value)
return 0;
flag_random_seed = NULL;
break;
case OPT_frandom_seed_:
flag_random_seed = arg;
break;
case OPT_fsched_stalled_insns_:
flag_sched_stalled_insns = value;
if (flag_sched_stalled_insns == 0)
flag_sched_stalled_insns = -1;
break;
case OPT_fstack_limit:
if (value)
return 0;
stack_limit_rtx = NULL_RTX;
break;
case OPT_fstack_limit_register_:
{
int reg = decode_reg_name (arg);
if (reg < 0)
error ("unrecognized register name \"%s\"", arg);
else
stack_limit_rtx = gen_rtx_REG (Pmode, reg);
}
break;
case OPT_fstack_limit_symbol_:
stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (arg));
break;
case OPT_ftree_vectorizer_verbose_:
vect_set_verbosity_level (arg);
break;
case OPT_ftls_model_:
if (!strcmp (arg, "global-dynamic"))
flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
else if (!strcmp (arg, "local-dynamic"))
flag_tls_default = TLS_MODEL_LOCAL_DYNAMIC;
else if (!strcmp (arg, "initial-exec"))
flag_tls_default = TLS_MODEL_INITIAL_EXEC;
else if (!strcmp (arg, "local-exec"))
flag_tls_default = TLS_MODEL_LOCAL_EXEC;
else
warning ("unknown tls-model \"%s\"", arg);
break;
case OPT_ftracer:
flag_tracer_set = true;
break;
case OPT_funroll_loops:
flag_unroll_loops_set = true;
break;
case OPT_fwritable_strings:
flag_writable_strings = value;
break;
case OPT_g:
set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg);
break;
case OPT_gcoff:
set_debug_level (SDB_DEBUG, false, arg);
break;
case OPT_gdwarf_2:
set_debug_level (DWARF2_DEBUG, false, arg);
break;
case OPT_ggdb:
set_debug_level (NO_DEBUG, 2, arg);
break;
case OPT_gstabs:
case OPT_gstabs_:
set_debug_level (DBX_DEBUG, code == OPT_gstabs_, arg);
break;
case OPT_gvms:
set_debug_level (VMS_DEBUG, false, arg);
break;
case OPT_gxcoff:
case OPT_gxcoff_:
set_debug_level (XCOFF_DEBUG, code == OPT_gxcoff_, arg);
break;
case OPT_m:
set_target_switch (arg);
break;
case OPT_o:
asm_file_name = arg;
break;
case OPT_pedantic_errors:
flag_pedantic_errors = pedantic = 1;
break;
default:
if (cl_options[scode].flag_var || cl_options[scode].access_flag)
break;
abort ();
}
return 1;
}
static void
handle_param (const char *carg)
{
char *equal, *arg;
int value;
arg = xstrdup (carg);
equal = strchr (arg, '=');
if (!equal)
error ("%s: --param arguments should be of the form NAME=VALUE", arg);
else
{
value = integral_argument (equal + 1);
if (value == -1)
error ("invalid --param value %qs", equal + 1);
else
{
*equal = '\0';
set_param_value (arg, value);
}
}
free (arg);
}
static void
set_Wextra (int setting)
{
extra_warnings = setting;
warn_unused_value = setting;
warn_unused_parameter = (setting && maybe_warn_unused_parameter);
if (setting == 0)
warn_uninitialized = 0;
else if (warn_uninitialized != 1)
warn_uninitialized = 2;
}
void
set_Wunused (int setting)
{
warn_unused_function = setting;
warn_unused_label = setting;
maybe_warn_unused_parameter = setting;
warn_unused_parameter = (setting && extra_warnings);
warn_unused_variable = setting;
warn_unused_value = setting;
}
void
set_fast_math_flags (int set)
{
flag_trapping_math = !set;
flag_unsafe_math_optimizations = set;
flag_finite_math_only = set;
flag_errno_math = !set;
if (set)
{
flag_signaling_nans = 0;
flag_rounding_math = 0;
flag_cx_limited_range = 1;
}
}
bool
fast_math_flags_set_p (void)
{
return (!flag_trapping_math
&& flag_unsafe_math_optimizations
&& flag_finite_math_only
&& !flag_errno_math);
}
static void
set_debug_level (enum debug_info_type type, int extended, const char *arg)
{
static bool type_explicit;
use_gnu_debug_info_extensions = extended;
if (type == NO_DEBUG)
{
if (write_symbols == NO_DEBUG)
{
write_symbols = PREFERRED_DEBUGGING_TYPE;
if (extended == 2)
{
#ifdef DWARF2_DEBUGGING_INFO
write_symbols = DWARF2_DEBUG;
#elif defined DBX_DEBUGGING_INFO
write_symbols = DBX_DEBUG;
#endif
}
if (write_symbols == NO_DEBUG)
warning ("target system does not support debug output");
}
}
else
{
if (type_explicit && write_symbols != NO_DEBUG && type != write_symbols)
error ("debug format \"%s\" conflicts with prior selection",
debug_type_names[type]);
write_symbols = type;
type_explicit = true;
}
if (*arg == '\0')
{
if (!debug_info_level)
debug_info_level = 2;
}
else
{
debug_info_level = integral_argument (arg);
if (debug_info_level == (unsigned int) -1)
error ("unrecognised debug output level \"%s\"", arg);
else if (debug_info_level > 3)
error ("debug output level %s is too high", arg);
}
}
static void
print_help (void)
{
size_t i;
const char *p;
GET_ENVIRONMENT (p, "COLUMNS");
if (p)
{
int value = atoi (p);
if (value > 0)
columns = value;
}
puts (_("The following options are language-independent:\n"));
print_filtered_help (CL_COMMON);
print_param_help ();
for (i = 0; lang_names[i]; i++)
{
printf (_("The %s front end recognizes the following options:\n\n"),
lang_names[i]);
print_filtered_help (1U << i);
}
display_target_options ();
}
static void
print_param_help (void)
{
size_t i;
puts (_("The --param option recognizes the following as parameters:\n"));
for (i = 0; i < LAST_PARAM; i++)
{
const char *help = compiler_params[i].help;
const char *param = compiler_params[i].option;
if (help == NULL || *help == '\0')
help = undocumented_msg;
help = _(help);
wrap_help (help, param, strlen (param));
}
putchar ('\n');
}
static void
print_filtered_help (unsigned int flag)
{
unsigned int i, len, filter, indent = 0;
bool duplicates = false;
const char *help, *opt, *tab;
static char *printed;
if (flag == CL_COMMON || flag == CL_TARGET)
{
filter = flag;
if (!printed)
printed = xmalloc (cl_options_count);
memset (printed, 0, cl_options_count);
}
else
{
filter = flag | CL_COMMON;
for (i = 0; i < cl_options_count; i++)
{
if ((cl_options[i].flags & filter) != flag)
continue;
if (cl_options[i].flags & CL_UNDOCUMENTED)
continue;
if (printed[i])
{
duplicates = true;
indent = print_switch (cl_options[i].opt_text, indent);
}
}
if (duplicates)
{
putchar ('\n');
putchar ('\n');
}
}
for (i = 0; i < cl_options_count; i++)
{
if ((cl_options[i].flags & filter) != flag)
continue;
if (cl_options[i].flags & CL_UNDOCUMENTED)
continue;
if (printed[i])
continue;
printed[i] = true;
help = cl_options[i].help;
if (!help)
help = undocumented_msg;
help = _(help);
tab = strchr (help, '\t');
if (tab)
{
len = tab - help;
opt = help;
help = tab + 1;
}
else
{
opt = cl_options[i].opt_text;
len = strlen (opt);
}
wrap_help (help, opt, len);
}
putchar ('\n');
}
static unsigned int
print_switch (const char *text, unsigned int indent)
{
unsigned int len = strlen (text) + 1;
if (indent)
{
putchar (',');
if (indent + len > columns)
{
putchar ('\n');
putchar (' ');
indent = 1;
}
}
else
putchar (' ');
putchar (' ');
fputs (text, stdout);
return indent + len + 1;
}
static void
wrap_help (const char *help, const char *item, unsigned int item_width)
{
unsigned int col_width = 27;
unsigned int remaining, room, len;
remaining = strlen (help);
do
{
room = columns - 3 - MAX (col_width, item_width);
if (room > columns)
room = 0;
len = remaining;
if (room < len)
{
unsigned int i;
for (i = 0; help[i]; i++)
{
if (i >= room && len != remaining)
break;
if (help[i] == ' ')
len = i;
else if ((help[i] == '-' || help[i] == '/')
&& help[i + 1] != ' '
&& i > 0 && ISALPHA (help[i - 1]))
len = i + 1;
}
}
printf( " %-*.*s %.*s\n", col_width, item_width, item, len, help);
item_width = 0;
while (help[len] == ' ')
len++;
help += len;
remaining -= len;
}
while (remaining);
}
static htab_t cl_perfunc_opts_hash_table;
static hashval_t
hash_cl_perfunc_opts (const void *p)
{
const unsigned int *uip = p;
unsigned int i;
hashval_t h = 0;
for (i = 0; i < sizeof (struct cl_perfunc_opts) / sizeof (int); i++)
h += *uip++;
return h;
}
static int
cmp_cl_perfunc_opts (const void *p, const void *q)
{
return !memcmp(p, q, sizeof(struct cl_perfunc_opts));
}
static struct cl_perfunc_opts *
make_perfunc_opts (void)
{
PTR *slot;
if (!cl_perfunc_opts_hash_table)
cl_perfunc_opts_hash_table = htab_create (11, hash_cl_perfunc_opts,
cmp_cl_perfunc_opts, NULL);
slot = htab_find_slot (cl_perfunc_opts_hash_table, &cl_pf_opts,
INSERT);
if (*slot == NULL)
{
*slot = xmalloc (sizeof (struct cl_perfunc_opts));
memcpy (*slot, &cl_pf_opts, sizeof (struct cl_perfunc_opts));
}
return *slot;
}
static htab_t func_cl_pf_opts_mapping_hash_table;
struct func_cl_pf_opts_mapping
{
tree func;
struct cl_perfunc_opts *cl_pf_opts;
};
static hashval_t
func_cl_pf_opts_mapping_hash (const void* entry)
{
const struct func_cl_pf_opts_mapping *e = entry;
return htab_hash_pointer (e->func);
}
static int
func_cl_pf_opts_mapping_eq (const void *p, const void *q)
{
const struct func_cl_pf_opts_mapping *pp = p;
const struct func_cl_pf_opts_mapping *qq = q;
return pp->func == qq->func;
}
void
record_func_cl_pf_opts_mapping (tree func)
{
PTR *slot;
struct func_cl_pf_opts_mapping map, *entry;
if (!func_cl_pf_opts_mapping_hash_table)
func_cl_pf_opts_mapping_hash_table = htab_create (101,
func_cl_pf_opts_mapping_hash, func_cl_pf_opts_mapping_eq, 0);
map.func = func;
slot = htab_find_slot (func_cl_pf_opts_mapping_hash_table, &map, INSERT);
if (*slot)
entry = *slot;
else
{
entry = xmalloc (sizeof (struct func_cl_pf_opts_mapping));
entry->func = func;
*slot = entry;
}
entry->cl_pf_opts = make_perfunc_opts ();
}
void
restore_func_cl_pf_opts_mapping (tree func)
{
PTR *slot;
struct func_cl_pf_opts_mapping map, *entry;
if (!func_cl_pf_opts_mapping_hash_table)
return;
map.func = func;
slot = htab_find_slot (func_cl_pf_opts_mapping_hash_table, &map, INSERT);
if (*slot)
entry = *slot;
else
{
entry = xmalloc (sizeof (struct func_cl_pf_opts_mapping));
entry->func = func;
entry->cl_pf_opts = &cl_pf_opts_cooked;
*slot = entry;
}
cl_pf_opts = *(entry->cl_pf_opts);
align_loops_log = floor_log2 (align_loops * 2 - 1);
align_jumps_log = floor_log2 (align_jumps * 2 - 1);
align_labels_log = floor_log2 (align_labels * 2 - 1);
if (align_labels_max_skip > align_labels || !align_labels)
align_labels_max_skip = align_labels - 1;
}
void
copy_func_cl_pf_opts_mapping (tree funcold, tree funcnew)
{
PTR *slot;
struct func_cl_pf_opts_mapping map, *entry;
struct cl_perfunc_opts *oldcl_pf_opts;
if (!func_cl_pf_opts_mapping_hash_table)
return;
map.func = funcold;
slot = htab_find_slot (func_cl_pf_opts_mapping_hash_table, &map, NO_INSERT);
gcc_assert (*slot);
entry = *slot;
oldcl_pf_opts = entry->cl_pf_opts;
map.func = funcnew;
slot = htab_find_slot (func_cl_pf_opts_mapping_hash_table, &map, INSERT);
if (*slot)
entry = *slot;
else
{
entry = xmalloc (sizeof (struct func_cl_pf_opts_mapping));
entry->func = funcnew;
*slot = entry;
}
entry->cl_pf_opts = oldcl_pf_opts;
}