diff options
Diffstat (limited to 'gcc/opts.c')
-rw-r--r-- | gcc/opts.c | 359 |
1 files changed, 264 insertions, 95 deletions
@@ -37,12 +37,137 @@ along with GCC; see the file COPYING3. If not see static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff); -/* Indexed by enum debug_info_type. */ +/* Names of fundamental debug info formats indexed by enum + debug_info_type. */ + const char *const debug_type_names[] = { - "none", "stabs", "dwarf-2", "xcoff", "vms" + "none", "stabs", "dwarf-2", "xcoff", "vms", "ctf", "btf" }; +/* Bitmasks of fundamental debug info formats indexed by enum + debug_info_type. */ + +static uint32_t debug_type_masks[] = +{ + NO_DEBUG, DBX_DEBUG, DWARF2_DEBUG, XCOFF_DEBUG, VMS_DEBUG, + CTF_DEBUG, BTF_DEBUG +}; + +/* Names of the set of debug formats requested by user. Updated and accessed + via debug_set_names. */ + +static char df_set_names[sizeof "none stabs dwarf-2 xcoff vms ctf btf"]; + +/* Get enum debug_info_type of the specified debug format, for error messages. + Can be used only for individual debug format types. */ + +enum debug_info_type +debug_set_to_format (uint32_t debug_info_set) +{ + int idx = 0; + enum debug_info_type dinfo_type = DINFO_TYPE_NONE; + /* Find first set bit. */ + if (debug_info_set) + idx = exact_log2 (debug_info_set & - debug_info_set); + /* Check that only one bit is set, if at all. This function is meant to be + used only for vanilla debug_info_set bitmask values, i.e. for individual + debug format types upto DINFO_TYPE_MAX. */ + gcc_assert ((debug_info_set & (debug_info_set - 1)) == 0); + dinfo_type = (enum debug_info_type)idx; + gcc_assert (dinfo_type <= DINFO_TYPE_MAX); + return dinfo_type; +} + +/* Get the number of debug formats enabled for output. */ + +unsigned int +debug_set_count (uint32_t w_symbols) +{ + unsigned int count = 0; + while (w_symbols) + { + ++ count; + w_symbols &= ~ (w_symbols & - w_symbols); + } + return count; +} + +/* Get the names of the debug formats enabled for output. */ + +const char * +debug_set_names (uint32_t w_symbols) +{ + uint32_t df_mask = 0; + /* Reset the string to be returned. */ + memset (df_set_names, 0, sizeof (df_set_names)); + /* Get the popcount. */ + int num_set_df = debug_set_count (w_symbols); + /* Iterate over the debug formats. Add name string for those enabled. */ + for (int i = DINFO_TYPE_NONE; i <= DINFO_TYPE_MAX; i++) + { + df_mask = debug_type_masks[i]; + if (w_symbols & df_mask) + { + strcat (df_set_names, debug_type_names[i]); + num_set_df--; + if (num_set_df) + strcat (df_set_names, " "); + else + break; + } + else if (!w_symbols) + { + /* No debug formats enabled. */ + gcc_assert (i == DINFO_TYPE_NONE); + strcat (df_set_names, debug_type_names[i]); + break; + } + } + return df_set_names; +} + +/* Return TRUE iff BTF debug info is enabled. */ + +bool +btf_debuginfo_p () +{ + return (write_symbols & BTF_DEBUG); +} + +/* Return TRUE iff BTF with CO-RE debug info is enabled. */ + +bool +btf_with_core_debuginfo_p () +{ + return (write_symbols & BTF_WITH_CORE_DEBUG); +} + +/* Return TRUE iff CTF debug info is enabled. */ + +bool +ctf_debuginfo_p () +{ + return (write_symbols & CTF_DEBUG); +} + +/* Return TRUE iff dwarf2 debug info is enabled. */ + +bool +dwarf_debuginfo_p () +{ + return (write_symbols & DWARF2_DEBUG); +} + +/* Return true iff the debug info format is to be generated based on DWARF + DIEs (like CTF and BTF debug info formats). */ + +bool dwarf_based_debuginfo_p () +{ + return ((write_symbols & CTF_DEBUG) + || (write_symbols & BTF_DEBUG)); +} + /* Parse the -femit-struct-debug-detailed option value and set the flag variables. */ @@ -190,7 +315,7 @@ static const char use_diagnosed_msg[] = N_("Uses of this option are diagnosed.") typedef char *char_p; /* For DEF_VEC_P. */ -static void set_debug_level (enum debug_info_type type, int extended, +static void set_debug_level (uint32_t dinfo, int extended, const char *arg, struct gcc_options *opts, struct gcc_options *opts_set, location_t loc); @@ -466,6 +591,7 @@ static const struct default_options default_options_table[] = { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fif_conversion2, NULL, 1 }, { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_finline_functions_called_once, NULL, 1 }, { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fmove_loop_invariants, NULL, 1 }, + { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fmove_loop_stores, NULL, 1 }, { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fssa_phiopt, NULL, 1 }, { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fipa_modref, NULL, 1 }, { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_bit_ccp, NULL, 1 }, @@ -688,37 +814,39 @@ control_options_for_live_patching (struct gcc_options *opts, switch (level) { case LIVE_PATCHING_INLINE_ONLY_STATIC: +#define LIVE_PATCHING_OPTION "-flive-patching=inline-only-static" if (opts_set->x_flag_ipa_cp_clone && opts->x_flag_ipa_cp_clone) error_at (loc, "%qs is incompatible with %qs", - "-fipa-cp-clone", "-flive-patching=inline-only-static"); + "-fipa-cp-clone", LIVE_PATCHING_OPTION); else opts->x_flag_ipa_cp_clone = 0; if (opts_set->x_flag_ipa_sra && opts->x_flag_ipa_sra) error_at (loc, "%qs is incompatible with %qs", - "-fipa-sra", "-flive-patching=inline-only-static"); + "-fipa-sra", LIVE_PATCHING_OPTION); else opts->x_flag_ipa_sra = 0; if (opts_set->x_flag_partial_inlining && opts->x_flag_partial_inlining) error_at (loc, "%qs is incompatible with %qs", - "-fpartial-inlining", "-flive-patching=inline-only-static"); + "-fpartial-inlining", LIVE_PATCHING_OPTION); else opts->x_flag_partial_inlining = 0; if (opts_set->x_flag_ipa_cp && opts->x_flag_ipa_cp) error_at (loc, "%qs is incompatible with %qs", - "-fipa-cp", "-flive-patching=inline-only-static"); + "-fipa-cp", LIVE_PATCHING_OPTION); else opts->x_flag_ipa_cp = 0; /* FALLTHROUGH. */ case LIVE_PATCHING_INLINE_CLONE: +#undef LIVE_PATCHING_OPTION +#define LIVE_PATCHING_OPTION "-flive-patching=inline-only-static|inline-clone" /* live patching should disable whole-program optimization. */ if (opts_set->x_flag_whole_program && opts->x_flag_whole_program) error_at (loc, "%qs is incompatible with %qs", - "-fwhole-program", - "-flive-patching=inline-only-static|inline-clone"); + "-fwhole-program", LIVE_PATCHING_OPTION); else opts->x_flag_whole_program = 0; @@ -728,71 +856,62 @@ control_options_for_live_patching (struct gcc_options *opts, if (opts_set->x_flag_ipa_pta && opts->x_flag_ipa_pta) error_at (loc, "%qs is incompatible with %qs", - "-fipa-pta", - "-flive-patching=inline-only-static|inline-clone"); + "-fipa-pta", LIVE_PATCHING_OPTION); else opts->x_flag_ipa_pta = 0; if (opts_set->x_flag_ipa_reference && opts->x_flag_ipa_reference) error_at (loc, "%qs is incompatible with %qs", - "-fipa-reference", - "-flive-patching=inline-only-static|inline-clone"); + "-fipa-reference", LIVE_PATCHING_OPTION); else opts->x_flag_ipa_reference = 0; if (opts_set->x_flag_ipa_ra && opts->x_flag_ipa_ra) error_at (loc, "%qs is incompatible with %qs", - "-fipa-ra", - "-flive-patching=inline-only-static|inline-clone"); + "-fipa-ra", LIVE_PATCHING_OPTION); else opts->x_flag_ipa_ra = 0; if (opts_set->x_flag_ipa_icf && opts->x_flag_ipa_icf) error_at (loc, "%qs is incompatible with %qs", - "-fipa-icf", - "-flive-patching=inline-only-static|inline-clone"); + "-fipa-icf", LIVE_PATCHING_OPTION); else opts->x_flag_ipa_icf = 0; if (opts_set->x_flag_ipa_icf_functions && opts->x_flag_ipa_icf_functions) error_at (loc, "%qs is incompatible with %qs", - "-fipa-icf-functions", - "-flive-patching=inline-only-static|inline-clone"); + "-fipa-icf-functions", LIVE_PATCHING_OPTION); else opts->x_flag_ipa_icf_functions = 0; if (opts_set->x_flag_ipa_icf_variables && opts->x_flag_ipa_icf_variables) error_at (loc, "%qs is incompatible with %qs", - "-fipa-icf-variables", - "-flive-patching=inline-only-static|inline-clone"); + "-fipa-icf-variables", LIVE_PATCHING_OPTION); else opts->x_flag_ipa_icf_variables = 0; if (opts_set->x_flag_ipa_bit_cp && opts->x_flag_ipa_bit_cp) error_at (loc, "%qs is incompatible with %qs", - "-fipa-bit-cp", - "-flive-patching=inline-only-static|inline-clone"); + "-fipa-bit-cp", LIVE_PATCHING_OPTION); else opts->x_flag_ipa_bit_cp = 0; if (opts_set->x_flag_ipa_vrp && opts->x_flag_ipa_vrp) error_at (loc, "%qs is incompatible with %qs", - "-fipa-vrp", - "-flive-patching=inline-only-static|inline-clone"); + "-fipa-vrp", LIVE_PATCHING_OPTION); else opts->x_flag_ipa_vrp = 0; if (opts_set->x_flag_ipa_pure_const && opts->x_flag_ipa_pure_const) error_at (loc, "%qs is incompatible with %qs", - "-fipa-pure-const", - "-flive-patching=inline-only-static|inline-clone"); + "-fipa-pure-const", LIVE_PATCHING_OPTION); else opts->x_flag_ipa_pure_const = 0; if (opts_set->x_flag_ipa_modref && opts->x_flag_ipa_modref) error_at (loc, - "%<-fipa-modref%> is incompatible with " - "%<-flive-patching=inline-only-static|inline-clone%>"); + "%<-fipa-modref%> is incompatible with %qs", + LIVE_PATCHING_OPTION); else opts->x_flag_ipa_modref = 0; @@ -802,8 +921,7 @@ control_options_for_live_patching (struct gcc_options *opts, if (opts_set->x_flag_ipa_reference_addressable && opts->x_flag_ipa_reference_addressable) error_at (loc, "%qs is incompatible with %qs", - "-fipa-reference-addressable", - "-flive-patching=inline-only-static|inline-clone"); + "-fipa-reference-addressable", LIVE_PATCHING_OPTION); else opts->x_flag_ipa_reference_addressable = 0; @@ -811,14 +929,15 @@ control_options_for_live_patching (struct gcc_options *opts, if (opts_set->x_flag_ipa_stack_alignment && opts->x_flag_ipa_stack_alignment) error_at (loc, "%qs is incompatible with %qs", - "-fipa-stack-alignment", - "-flive-patching=inline-only-static|inline-clone"); + "-fipa-stack-alignment", LIVE_PATCHING_OPTION); else opts->x_flag_ipa_stack_alignment = 0; break; default: gcc_unreachable (); } + +#undef LIVE_PATCHING_OPTION } /* --help option argument if set. */ @@ -1817,17 +1936,6 @@ const struct sanitizer_opts_s sanitizer_opts[] = { NULL, 0U, 0UL, false } }; -/* -f{,no-}sanitize-coverage= suboptions. */ -const struct sanitizer_opts_s coverage_sanitizer_opts[] = -{ -#define COVERAGE_SANITIZER_OPT(name, flags) \ - { #name, flags, sizeof #name - 1, true } - COVERAGE_SANITIZER_OPT (trace-pc, SANITIZE_COV_TRACE_PC), - COVERAGE_SANITIZER_OPT (trace-cmp, SANITIZE_COV_TRACE_CMP), -#undef COVERAGE_SANITIZER_OPT - { NULL, 0U, 0UL, false } -}; - /* -fzero-call-used-regs= suboptions. */ const struct zero_call_used_regs_opts_s zero_call_used_regs_opts[] = { @@ -1878,8 +1986,7 @@ struct edit_distance_traits<const string_fragment &> /* Given ARG, an unrecognized sanitizer option, return the best matching sanitizer option, or NULL if there isn't one. OPTS is array of candidate sanitizer options. - CODE is OPT_fsanitize_, OPT_fsanitize_recover_ or - OPT_fsanitize_coverage_. + CODE is OPT_fsanitize_ or OPT_fsanitize_recover_. VALUE is non-zero for the regular form of the option, zero for the "no-" form (e.g. "-fno-sanitize-recover="). */ @@ -1919,12 +2026,6 @@ parse_sanitizer_options (const char *p, location_t loc, int scode, { enum opt_code code = (enum opt_code) scode; - const struct sanitizer_opts_s *opts; - if (code == OPT_fsanitize_coverage_) - opts = coverage_sanitizer_opts; - else - opts = sanitizer_opts; - while (*p != 0) { size_t len, i; @@ -1942,11 +2043,12 @@ parse_sanitizer_options (const char *p, location_t loc, int scode, } /* Check to see if the string matches an option class name. */ - for (i = 0; opts[i].name != NULL; ++i) - if (len == opts[i].len && memcmp (p, opts[i].name, len) == 0) + for (i = 0; sanitizer_opts[i].name != NULL; ++i) + if (len == sanitizer_opts[i].len + && memcmp (p, sanitizer_opts[i].name, len) == 0) { /* Handle both -fsanitize and -fno-sanitize cases. */ - if (value && opts[i].flag == ~0U) + if (value && sanitizer_opts[i].flag == ~0U) { if (code == OPT_fsanitize_) { @@ -1963,14 +2065,14 @@ parse_sanitizer_options (const char *p, location_t loc, int scode, -fsanitize-recover=return if -fsanitize-recover=undefined is selected. */ if (code == OPT_fsanitize_recover_ - && opts[i].flag == SANITIZE_UNDEFINED) + && sanitizer_opts[i].flag == SANITIZE_UNDEFINED) flags |= (SANITIZE_UNDEFINED & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN)); else - flags |= opts[i].flag; + flags |= sanitizer_opts[i].flag; } else - flags &= ~opts[i].flag; + flags &= ~sanitizer_opts[i].flag; found = true; break; } @@ -1979,13 +2081,11 @@ parse_sanitizer_options (const char *p, location_t loc, int scode, { const char *hint = get_closest_sanitizer_option (string_fragment (p, len), - opts, code, value); + sanitizer_opts, code, value); const char *suffix; if (code == OPT_fsanitize_recover_) suffix = "-recover"; - else if (code == OPT_fsanitize_coverage_) - suffix = "-coverage"; else suffix = ""; @@ -2436,9 +2536,7 @@ common_handle_option (struct gcc_options *opts, break; case OPT_fsanitize_coverage_: - opts->x_flag_sanitize_coverage - = parse_sanitizer_options (arg, loc, code, - opts->x_flag_sanitize_coverage, value, true); + opts->x_flag_sanitize_coverage = value; break; case OPT_O: @@ -2636,16 +2734,18 @@ common_handle_option (struct gcc_options *opts, /* Deferred. */ break; - case OPT_foffload_: + case OPT_foffload_options_: /* Deferred. */ break; -#ifndef ACCEL_COMPILER case OPT_foffload_abi_: +#ifdef ACCEL_COMPILER + /* Handled in the 'mkoffload's. */ +#else error_at (loc, "%<-foffload-abi%> option can be specified only for " "offload compiler"); - break; #endif + break; case OPT_fpack_struct_: if (value <= 0 || (value & (value - 1)) || value > 16) @@ -2798,6 +2898,24 @@ common_handle_option (struct gcc_options *opts, loc); break; + case OPT_gbtf: + set_debug_level (BTF_DEBUG, false, arg, opts, opts_set, loc); + /* set the debug level to level 2, but if already at level 3, + don't lower it. */ + if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL) + opts->x_debug_info_level = DINFO_LEVEL_NORMAL; + break; + + case OPT_gctf: + set_debug_level (CTF_DEBUG, false, arg, opts, opts_set, loc); + /* CTF generation feeds off DWARF dies. For optimal CTF, switch debug + info level to 2. If off or at level 1, set it to level 2, but if + already at level 3, don't lower it. */ + if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL + && opts->x_ctf_debug_info_level > CTFINFO_LEVEL_NONE) + opts->x_debug_info_level = DINFO_LEVEL_NORMAL; + break; + case OPT_gdwarf: if (arg && strlen (arg) != 0) { @@ -3027,17 +3145,17 @@ fast_math_flags_struct_set_p (struct cl_optimization *opt) } /* Handle a debug output -g switch for options OPTS - (OPTS_SET->x_write_symbols storing whether a debug type was passed + (OPTS_SET->x_write_symbols storing whether a debug format was passed explicitly), location LOC. EXTENDED is true or false to support extended output (2 is special and means "-ggdb" was given). */ static void -set_debug_level (enum debug_info_type type, int extended, const char *arg, +set_debug_level (uint32_t dinfo, int extended, const char *arg, struct gcc_options *opts, struct gcc_options *opts_set, location_t loc) { opts->x_use_gnu_debug_info_extensions = extended; - if (type == NO_DEBUG) + if (dinfo == NO_DEBUG) { if (opts->x_write_symbols == NO_DEBUG) { @@ -3046,7 +3164,10 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg, if (extended == 2) { #if defined DWARF2_DEBUGGING_INFO || defined DWARF2_LINENO_DEBUGGING_INFO - opts->x_write_symbols = DWARF2_DEBUG; + if (opts->x_write_symbols & CTF_DEBUG) + opts->x_write_symbols |= DWARF2_DEBUG; + else + opts->x_write_symbols = DWARF2_DEBUG; #elif defined DBX_DEBUGGING_INFO opts->x_write_symbols = DBX_DEBUG; #endif @@ -3055,37 +3176,81 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg, if (opts->x_write_symbols == NO_DEBUG) warning_at (loc, 0, "target system does not support debug output"); } + else if ((opts->x_write_symbols & CTF_DEBUG) + || (opts->x_write_symbols & BTF_DEBUG)) + { + opts->x_write_symbols |= DWARF2_DEBUG; + opts_set->x_write_symbols |= DWARF2_DEBUG; + } } else { - /* Does it conflict with an already selected type? */ - if (opts_set->x_write_symbols != NO_DEBUG - && opts->x_write_symbols != NO_DEBUG - && type != opts->x_write_symbols) - error_at (loc, "debug format %qs conflicts with prior selection", - debug_type_names[type]); - opts->x_write_symbols = type; - opts_set->x_write_symbols = type; + /* Make and retain the choice if both CTF and DWARF debug info are to + be generated. */ + if (((dinfo == DWARF2_DEBUG) || (dinfo == CTF_DEBUG)) + && ((opts->x_write_symbols == (DWARF2_DEBUG|CTF_DEBUG)) + || (opts->x_write_symbols == DWARF2_DEBUG) + || (opts->x_write_symbols == CTF_DEBUG))) + { + opts->x_write_symbols |= dinfo; + opts_set->x_write_symbols |= dinfo; + } + /* However, CTF and BTF are not allowed together at this time. */ + else if (((dinfo == DWARF2_DEBUG) || (dinfo == BTF_DEBUG)) + && ((opts->x_write_symbols == (DWARF2_DEBUG|BTF_DEBUG)) + || (opts->x_write_symbols == DWARF2_DEBUG) + || (opts->x_write_symbols == BTF_DEBUG))) + { + opts->x_write_symbols |= dinfo; + opts_set->x_write_symbols |= dinfo; + } + else + { + /* Does it conflict with an already selected debug format? */ + if (opts_set->x_write_symbols != NO_DEBUG + && opts->x_write_symbols != NO_DEBUG + && dinfo != opts->x_write_symbols) + { + gcc_assert (debug_set_count (dinfo) <= 1); + error_at (loc, "debug format %qs conflicts with prior selection", + debug_type_names[debug_set_to_format (dinfo)]); + } + opts->x_write_symbols = dinfo; + opts_set->x_write_symbols = dinfo; + } } - /* A debug flag without a level defaults to level 2. - If off or at level 1, set it to level 2, but if already - at level 3, don't lower it. */ - if (*arg == '\0') + if (dinfo != BTF_DEBUG) { - if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL) - opts->x_debug_info_level = DINFO_LEVEL_NORMAL; - } - else - { - int argval = integral_argument (arg); - if (argval == -1) - error_at (loc, "unrecognized debug output level %qs", arg); - else if (argval > 3) - error_at (loc, "debug output level %qs is too high", arg); + /* A debug flag without a level defaults to level 2. + If off or at level 1, set it to level 2, but if already + at level 3, don't lower it. */ + if (*arg == '\0') + { + if (dinfo == CTF_DEBUG) + opts->x_ctf_debug_info_level = CTFINFO_LEVEL_NORMAL; + else if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL) + opts->x_debug_info_level = DINFO_LEVEL_NORMAL; + } else - opts->x_debug_info_level = (enum debug_info_levels) argval; + { + int argval = integral_argument (arg); + if (argval == -1) + error_at (loc, "unrecognized debug output level %qs", arg); + else if (argval > 3) + error_at (loc, "debug output level %qs is too high", arg); + else + { + if (dinfo == CTF_DEBUG) + opts->x_ctf_debug_info_level + = (enum ctf_debug_info_levels) argval; + else + opts->x_debug_info_level = (enum debug_info_levels) argval; + } + } } + else if (*arg != '\0') + error_at (loc, "unrecognized btf debug output level %qs", arg); } /* Arrange to dump core on error for diagnostic context DC. (The @@ -3243,9 +3408,13 @@ get_option_html_page (int option_index) const cl_option *cl_opt = &cl_options[option_index]; /* Analyzer options are on their own page. */ - if (strstr(cl_opt->opt_text, "analyzer-")) + if (strstr (cl_opt->opt_text, "analyzer-")) return "gcc/Static-Analyzer-Options.html"; + /* Handle -flto= option. */ + if (strstr (cl_opt->opt_text, "flto")) + return "gcc/Optimize-Options.html"; + #ifdef CL_Fortran if ((cl_opt->flags & CL_Fortran) != 0 /* If it is option common to both C/C++ and Fortran, it is documented |