From fcfe3c2dc69dc83fd85bb0887e13af57e5002157 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 23 Nov 2020 13:40:04 +0100 Subject: [PATCH] Refactor -frecord-gcc-switches. gcc/ChangeLog: * doc/tm.texi: Change argument of the record_gcc_switches hook and remove SWITCH_TYPE_* enum values. * dwarf2out.c (gen_producer_string): Move to opts.c and remove handling of the dwarf_record_gcc_switches option. (dwarf2out_early_finish): Use moved gen_producer_string function. * opts.c (gen_producer_string): New. * opts.h (gen_producer_string): New. * target.def: Change type of record_gcc_switches. * target.h (enum print_switch_type): Remove. (elf_record_gcc_switches): Change first argument. * toplev.c (MAX_LINE): Remove. (print_to_asm_out_file): Likewise. (print_to_stderr): Likewise. (print_single_switch): Likewise. (print_switch_values): Likewise. (init_asm_output): Use new gen_producer_string function. (process_options): Likewise. * varasm.c (elf_record_gcc_switches): Just save the string argument to the ELF container. --- gcc/doc/tm.texi | 38 +---------- gcc/dwarf2out.c | 118 +++------------------------------ gcc/opts.c | 108 ++++++++++++++++++++++++++++++ gcc/opts.h | 4 ++ gcc/target.def | 38 +---------- gcc/target.h | 14 +--- gcc/toplev.c | 172 ++++-------------------------------------------- gcc/varasm.c | 48 +++----------- 8 files changed, 149 insertions(+), 391 deletions(-) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 2b88f78944f..baee63a3700 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -8077,43 +8077,9 @@ need to override this if your target has special flags that might be set via @code{__attribute__}. @end deftypefn -@deftypefn {Target Hook} int TARGET_ASM_RECORD_GCC_SWITCHES (print_switch_type @var{type}, const char *@var{text}) +@deftypefn {Target Hook} void TARGET_ASM_RECORD_GCC_SWITCHES (const char *@var{}) Provides the target with the ability to record the gcc command line -switches that have been passed to the compiler, and options that are -enabled. The @var{type} argument specifies what is being recorded. -It can take the following values: - -@table @gcctabopt -@item SWITCH_TYPE_PASSED -@var{text} is a command line switch that has been set by the user. - -@item SWITCH_TYPE_ENABLED -@var{text} is an option which has been enabled. This might be as a -direct result of a command line switch, or because it is enabled by -default or because it has been enabled as a side effect of a different -command line switch. For example, the @option{-O2} switch enables -various different individual optimization passes. - -@item SWITCH_TYPE_DESCRIPTIVE -@var{text} is either NULL or some descriptive text which should be -ignored. If @var{text} is NULL then it is being used to warn the -target hook that either recording is starting or ending. The first -time @var{type} is SWITCH_TYPE_DESCRIPTIVE and @var{text} is NULL, the -warning is for start up and the second time the warning is for -wind down. This feature is to allow the target hook to make any -necessary preparations before it starts to record switches and to -perform any necessary tidying up after it has finished recording -switches. - -@item SWITCH_TYPE_LINE_START -This option can be ignored by this target hook. - -@item SWITCH_TYPE_LINE_END -This option can be ignored by this target hook. -@end table - -The hook's return value must be zero. Other return values may be -supported in the future. +switches provided as argument. By default this hook is set to NULL, but an example implementation is provided for ELF based targets. Called @var{elf_record_gcc_switches}, diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 01e7ae183d5..82303751fce 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -24427,115 +24427,6 @@ gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die) static char *producer_string; -/* Return a heap allocated producer string including command line options - if -grecord-gcc-switches. */ - -static char * -gen_producer_string (void) -{ - size_t j; - auto_vec switches; - const char *language_string = lang_hooks.name; - char *producer, *tail; - const char *p; - size_t len = dwarf_record_gcc_switches ? 0 : 3; - size_t plen = strlen (language_string) + 1 + strlen (version_string); - - for (j = 1; dwarf_record_gcc_switches && j < save_decoded_options_count; j++) - switch (save_decoded_options[j].opt_index) - { - case OPT_o: - case OPT_d: - case OPT_dumpbase: - case OPT_dumpbase_ext: - case OPT_dumpdir: - case OPT_quiet: - case OPT_version: - case OPT_v: - case OPT_w: - case OPT_L: - case OPT_D: - case OPT_I: - case OPT_U: - case OPT_SPECIAL_unknown: - case OPT_SPECIAL_ignore: - case OPT_SPECIAL_warn_removed: - case OPT_SPECIAL_program_name: - case OPT_SPECIAL_input_file: - case OPT_grecord_gcc_switches: - case OPT__output_pch_: - case OPT_fdiagnostics_show_location_: - case OPT_fdiagnostics_show_option: - case OPT_fdiagnostics_show_caret: - case OPT_fdiagnostics_show_labels: - case OPT_fdiagnostics_show_line_numbers: - case OPT_fdiagnostics_color_: - case OPT_fdiagnostics_format_: - case OPT_fverbose_asm: - case OPT____: - case OPT__sysroot_: - case OPT_nostdinc: - case OPT_nostdinc__: - case OPT_fpreprocessed: - case OPT_fltrans_output_list_: - case OPT_fresolution_: - case OPT_fdebug_prefix_map_: - case OPT_fmacro_prefix_map_: - case OPT_ffile_prefix_map_: - case OPT_fcompare_debug: - case OPT_fchecking: - case OPT_fchecking_: - /* Ignore these. */ - continue; - case OPT_flto_: - { - const char *lto_canonical = "-flto"; - switches.safe_push (lto_canonical); - len += strlen (lto_canonical) + 1; - break; - } - default: - if (cl_options[save_decoded_options[j].opt_index].flags - & CL_NO_DWARF_RECORD) - continue; - gcc_checking_assert (save_decoded_options[j].canonical_option[0][0] - == '-'); - switch (save_decoded_options[j].canonical_option[0][1]) - { - case 'M': - case 'i': - case 'W': - continue; - case 'f': - if (strncmp (save_decoded_options[j].canonical_option[0] + 2, - "dump", 4) == 0) - continue; - break; - default: - break; - } - switches.safe_push (save_decoded_options[j].orig_option_with_args_text); - len += strlen (save_decoded_options[j].orig_option_with_args_text) + 1; - break; - } - - producer = XNEWVEC (char, plen + 1 + len + 1); - tail = producer; - sprintf (tail, "%s %s", language_string, version_string); - tail += plen; - - FOR_EACH_VEC_ELT (switches, j, p) - { - len = strlen (p); - *tail = ' '; - memcpy (tail + 1, p, len); - tail += len + 1; - } - - *tail = '\0'; - return producer; -} - /* Given a C and/or C++ language/version string return the "highest". C++ is assumed to be "higher" than C in this case. Used for merging LTO translation unit languages. */ @@ -32145,7 +32036,14 @@ dwarf2out_early_finish (const char *filename) header compilation, so always fill it with empty string initially and overwrite only here. */ dw_attr_node *producer = get_AT (comp_unit_die (), DW_AT_producer); - producer_string = gen_producer_string (); + + if (dwarf_record_gcc_switches) + producer_string = gen_producer_string (lang_hooks.name, + save_decoded_options, + save_decoded_options_count); + else + producer_string = concat (lang_hooks.name, " ", version_string, NULL); + producer->dw_attr_val.v.val_str->refcount--; producer->dw_attr_val.v.val_str = find_AT_string (producer_string); diff --git a/gcc/opts.c b/gcc/opts.c index 57774916a09..1be7c43aa09 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "spellcheck.h" #include "opt-suggestions.h" #include "diagnostic-color.h" +#include "version.h" #include "selftest.h" static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff); @@ -3200,6 +3201,113 @@ get_option_url (diagnostic_context *, int option_index) return NULL; } +/* Return a heap allocated producer string including command line options. */ + +char * +gen_producer_string (const char *language_string, cl_decoded_option *options, + unsigned int options_count) +{ + size_t j; + auto_vec switches; + char *producer, *tail; + const char *p; + size_t len = 0; + size_t plen = strlen (language_string) + 1 + strlen (version_string); + + for (j = 0; j < options_count; j++) + switch (options[j].opt_index) + { + case OPT_o: + case OPT_d: + case OPT_dumpbase: + case OPT_dumpdir: + case OPT_quiet: + case OPT_version: + case OPT_v: + case OPT_w: + case OPT_L: + case OPT_D: + case OPT_I: + case OPT_U: + case OPT_SPECIAL_unknown: + case OPT_SPECIAL_ignore: + case OPT_SPECIAL_warn_removed: + case OPT_SPECIAL_program_name: + case OPT_SPECIAL_input_file: + case OPT_grecord_gcc_switches: + case OPT_frecord_gcc_switches: + case OPT__output_pch_: + case OPT_fdiagnostics_show_location_: + case OPT_fdiagnostics_show_option: + case OPT_fdiagnostics_show_caret: + case OPT_fdiagnostics_show_labels: + case OPT_fdiagnostics_show_line_numbers: + case OPT_fdiagnostics_color_: + case OPT_fdiagnostics_format_: + case OPT_fverbose_asm: + case OPT____: + case OPT__sysroot_: + case OPT_nostdinc: + case OPT_nostdinc__: + case OPT_fpreprocessed: + case OPT_fltrans_output_list_: + case OPT_fresolution_: + case OPT_fdebug_prefix_map_: + case OPT_fmacro_prefix_map_: + case OPT_ffile_prefix_map_: + case OPT_fcompare_debug: + case OPT_fchecking: + case OPT_fchecking_: + /* Ignore these. */ + continue; + case OPT_flto_: + { + const char *lto_canonical = "-flto"; + switches.safe_push (lto_canonical); + len += strlen (lto_canonical) + 1; + break; + } + default: + if (cl_options[options[j].opt_index].flags + & CL_NO_DWARF_RECORD) + continue; + gcc_checking_assert (options[j].canonical_option[0][0] == '-'); + switch (options[j].canonical_option[0][1]) + { + case 'M': + case 'i': + case 'W': + continue; + case 'f': + if (strncmp (options[j].canonical_option[0] + 2, + "dump", 4) == 0) + continue; + break; + default: + break; + } + switches.safe_push (options[j].orig_option_with_args_text); + len += strlen (options[j].orig_option_with_args_text) + 1; + break; + } + + producer = XNEWVEC (char, plen + 1 + len + 1); + tail = producer; + sprintf (tail, "%s %s", language_string, version_string); + tail += plen; + + FOR_EACH_VEC_ELT (switches, j, p) + { + len = strlen (p); + *tail = ' '; + memcpy (tail + 1, p, len); + tail += len + 1; + } + + *tail = '\0'; + return producer; +} + #if CHECKING_P namespace selftest { diff --git a/gcc/opts.h b/gcc/opts.h index d62bfcfdf6a..4ad6b2571f9 100644 --- a/gcc/opts.h +++ b/gcc/opts.h @@ -482,6 +482,10 @@ extern void parse_options_from_collect_gcc_options (const char *, obstack *, extern void prepend_xassembler_to_collect_as_options (const char *, obstack *); +extern char *gen_producer_string (const char *language_string, + cl_decoded_option *options, + unsigned int options_count); + /* Set OPTION in OPTS to VALUE if the option is not set in OPTS_SET. */ #define SET_OPTION_IF_UNSET(OPTS, OPTS_SET, OPTION, VALUE) \ diff --git a/gcc/target.def b/gcc/target.def index 810d5542c28..62b409507c9 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -757,41 +757,7 @@ directive to annotate @var{symbol} as used. The Darwin target uses the\n\ DEFHOOK (record_gcc_switches, "Provides the target with the ability to record the gcc command line\n\ -switches that have been passed to the compiler, and options that are\n\ -enabled. The @var{type} argument specifies what is being recorded.\n\ -It can take the following values:\n\ -\n\ -@table @gcctabopt\n\ -@item SWITCH_TYPE_PASSED\n\ -@var{text} is a command line switch that has been set by the user.\n\ -\n\ -@item SWITCH_TYPE_ENABLED\n\ -@var{text} is an option which has been enabled. This might be as a\n\ -direct result of a command line switch, or because it is enabled by\n\ -default or because it has been enabled as a side effect of a different\n\ -command line switch. For example, the @option{-O2} switch enables\n\ -various different individual optimization passes.\n\ -\n\ -@item SWITCH_TYPE_DESCRIPTIVE\n\ -@var{text} is either NULL or some descriptive text which should be\n\ -ignored. If @var{text} is NULL then it is being used to warn the\n\ -target hook that either recording is starting or ending. The first\n\ -time @var{type} is SWITCH_TYPE_DESCRIPTIVE and @var{text} is NULL, the\n\ -warning is for start up and the second time the warning is for\n\ -wind down. This feature is to allow the target hook to make any\n\ -necessary preparations before it starts to record switches and to\n\ -perform any necessary tidying up after it has finished recording\n\ -switches.\n\ -\n\ -@item SWITCH_TYPE_LINE_START\n\ -This option can be ignored by this target hook.\n\ -\n\ -@item SWITCH_TYPE_LINE_END\n\ -This option can be ignored by this target hook.\n\ -@end table\n\ -\n\ -The hook's return value must be zero. Other return values may be\n\ -supported in the future.\n\ +switches provided as argument.\n\ \n\ By default this hook is set to NULL, but an example implementation is\n\ provided for ELF based targets. Called @var{elf_record_gcc_switches},\n\ @@ -799,7 +765,7 @@ it records the switches as ASCII text inside a new, string mergeable\n\ section in the assembler output file. The name of the new section is\n\ provided by the @code{TARGET_ASM_RECORD_GCC_SWITCHES_SECTION} target\n\ hook.", - int, (print_switch_type type, const char *text), + void, (const char *), NULL) /* The name of the section that the example ELF implementation of diff --git a/gcc/target.h b/gcc/target.h index 440cd25f297..960188023f1 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -68,16 +68,6 @@ union cumulative_args_t { void *p; }; #endif /* !CHECKING_P */ -/* Types used by the record_gcc_switches() target function. */ -enum print_switch_type -{ - SWITCH_TYPE_PASSED, /* A switch passed on the command line. */ - SWITCH_TYPE_ENABLED, /* An option that is currently enabled. */ - SWITCH_TYPE_DESCRIPTIVE, /* Descriptive text, not a switch or option. */ - SWITCH_TYPE_LINE_START, /* Please emit any necessary text at the start of a line. */ - SWITCH_TYPE_LINE_END /* Please emit a line terminator. */ -}; - /* Types of memory operation understood by the "by_pieces" infrastructure. Used by the TARGET_USE_BY_PIECES_INFRASTRUCTURE_P target hook and internally by the functions in expr.c. */ @@ -96,10 +86,8 @@ extern unsigned HOST_WIDE_INT by_pieces_ninsns (unsigned HOST_WIDE_INT, unsigned int, by_pieces_operation); -typedef int (* print_switch_fn_type) (print_switch_type, const char *); - /* An example implementation for ELF targets. Defined in varasm.c */ -extern int elf_record_gcc_switches (print_switch_type type, const char *); +extern void elf_record_gcc_switches (const char *); /* Some places still assume that all pointer or address modes are the standard Pmode and ptr_mode. These optimizations become invalid if diff --git a/gcc/toplev.c b/gcc/toplev.c index e0e0e04e95f..d7583b496d2 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -116,9 +116,6 @@ static void compile_file (void); /* True if we don't need a backend (e.g. preprocessing only). */ static bool no_backend; -/* Length of line when printing switch values. */ -#define MAX_LINE 75 - /* Decoded options, and number of such options. */ struct cl_decoded_option *save_decoded_options; unsigned int save_decoded_options_count; @@ -684,148 +681,7 @@ print_version (FILE *file, const char *indent, bool show_global_state) } } -static int -print_to_asm_out_file (print_switch_type type, const char * text) -{ - bool prepend_sep = true; - - switch (type) - { - case SWITCH_TYPE_LINE_END: - putc ('\n', asm_out_file); - return 1; - - case SWITCH_TYPE_LINE_START: - fputs (ASM_COMMENT_START, asm_out_file); - return strlen (ASM_COMMENT_START); - - case SWITCH_TYPE_DESCRIPTIVE: - if (ASM_COMMENT_START[0] == 0) - prepend_sep = false; - /* FALLTHRU */ - case SWITCH_TYPE_PASSED: - case SWITCH_TYPE_ENABLED: - if (prepend_sep) - fputc (' ', asm_out_file); - fputs (text, asm_out_file); - /* No need to return the length here as - print_single_switch has already done it. */ - return 0; - - default: - return -1; - } -} - -static int -print_to_stderr (print_switch_type type, const char * text) -{ - switch (type) - { - case SWITCH_TYPE_LINE_END: - putc ('\n', stderr); - return 1; - - case SWITCH_TYPE_LINE_START: - return 0; - - case SWITCH_TYPE_PASSED: - case SWITCH_TYPE_ENABLED: - fputc (' ', stderr); - /* FALLTHRU */ - - case SWITCH_TYPE_DESCRIPTIVE: - fputs (text, stderr); - /* No need to return the length here as - print_single_switch has already done it. */ - return 0; - - default: - return -1; - } -} - -/* Print an option value and return the adjusted position in the line. - ??? print_fn doesn't handle errors, eg disk full; presumably other - code will catch a disk full though. */ - -static int -print_single_switch (print_switch_fn_type print_fn, - int pos, - print_switch_type type, - const char * text) -{ - /* The ultrix fprintf returns 0 on success, so compute the result - we want here since we need it for the following test. The +1 - is for the separator character that will probably be emitted. */ - int len = strlen (text) + 1; - - if (pos != 0 - && pos + len > MAX_LINE) - { - print_fn (SWITCH_TYPE_LINE_END, NULL); - pos = 0; - } - - if (pos == 0) - pos += print_fn (SWITCH_TYPE_LINE_START, NULL); - - print_fn (type, text); - return pos + len; -} - -/* Print active target switches using PRINT_FN. - POS is the current cursor position and MAX is the size of a "line". - Each line begins with INDENT and ends with TERM. - Each switch is separated from the next by SEP. */ - -static void -print_switch_values (print_switch_fn_type print_fn) -{ - int pos = 0; - size_t j; - - /* Print the options as passed. */ - pos = print_single_switch (print_fn, pos, - SWITCH_TYPE_DESCRIPTIVE, _("options passed: ")); - for (j = 1; j < save_decoded_options_count; j++) - { - switch (save_decoded_options[j].opt_index) - { - case OPT_o: - case OPT_d: - case OPT_dumpbase: - case OPT_dumpbase_ext: - case OPT_dumpdir: - case OPT_quiet: - case OPT_version: - /* Ignore these. */ - continue; - } - - pos = print_single_switch (print_fn, pos, SWITCH_TYPE_PASSED, - save_decoded_options[j].orig_option_with_args_text); - } - - if (pos > 0) - print_fn (SWITCH_TYPE_LINE_END, NULL); - - /* Print the -f and -m options that have been enabled. - We don't handle language specific options but printing argv - should suffice. */ - pos = print_single_switch (print_fn, 0, - SWITCH_TYPE_DESCRIPTIVE, _("options enabled: ")); - - unsigned lang_mask = lang_hooks.option_lang_mask (); - for (j = 0; j < cl_options_count; j++) - if (cl_options[j].cl_report - && option_enabled (j, lang_mask, &global_options) > 0) - pos = print_single_switch (print_fn, pos, - SWITCH_TYPE_ENABLED, cl_options[j].opt_text); - - print_fn (SWITCH_TYPE_LINE_END, NULL); -} /* Open assembly code output file. Do this even if -fsyntax-only is on, because then the driver will have provided the name of a @@ -872,14 +728,11 @@ init_asm_output (const char *name) { if (targetm.asm_out.record_gcc_switches) { - /* Let the target know that we are about to start recording. */ - targetm.asm_out.record_gcc_switches (SWITCH_TYPE_DESCRIPTIVE, - NULL); - /* Now record the switches. */ - print_switch_values (targetm.asm_out.record_gcc_switches); - /* Let the target know that the recording is over. */ - targetm.asm_out.record_gcc_switches (SWITCH_TYPE_DESCRIPTIVE, - NULL); + const char *str + = gen_producer_string (lang_hooks.name, + save_decoded_options, + save_decoded_options_count); + targetm.asm_out.record_gcc_switches (str); } else inform (UNKNOWN_LOCATION, @@ -889,11 +742,13 @@ init_asm_output (const char *name) if (flag_verbose_asm) { - /* Print the list of switches in effect - into the assembler file as comments. */ print_version (asm_out_file, ASM_COMMENT_START, true); - print_switch_values (print_to_asm_out_file); - putc ('\n', asm_out_file); + fputs (ASM_COMMENT_START, asm_out_file); + fputc (' ', asm_out_file); + fputs (gen_producer_string (lang_hooks.name, save_decoded_options, + save_decoded_options_count), + asm_out_file); + fputc ('\n', asm_out_file); } } } @@ -1523,8 +1378,9 @@ process_options (void) if (version_flag) { print_version (stderr, "", true); - if (! quiet_flag) - print_switch_values (print_to_stderr); + if (!quiet_flag) + fputs (gen_producer_string (lang_hooks.name, save_decoded_options, + save_decoded_options_count), stderr); } if (flag_syntax_only) diff --git a/gcc/varasm.c b/gcc/varasm.c index b92da26fb82..64f82b90fb6 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see #include "fold-const.h" #include "stor-layout.h" #include "varasm.h" +#include "version.h" #include "flags.h" #include "stmt.h" #include "expr.h" @@ -58,6 +59,8 @@ along with GCC; see the file COPYING3. If not see #include "rtl-iter.h" #include "file-prefix-map.h" /* remap_debug_filename() */ #include "alloc-pool.h" +#include "toplev.h" +#include "opts.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data declarations. */ @@ -8034,45 +8037,14 @@ output_object_blocks (void) we want to emit NUL strings terminators into the object file we have to use ASM_OUTPUT_SKIP. */ -int -elf_record_gcc_switches (print_switch_type type, const char * name) +void +elf_record_gcc_switches (const char *options) { - switch (type) - { - case SWITCH_TYPE_PASSED: - ASM_OUTPUT_ASCII (asm_out_file, name, strlen (name)); - ASM_OUTPUT_SKIP (asm_out_file, HOST_WIDE_INT_1U); - break; - - case SWITCH_TYPE_DESCRIPTIVE: - if (name == NULL) - { - /* Distinguish between invocations where name is NULL. */ - static bool started = false; - - if (!started) - { - section * sec; - - sec = get_section (targetm.asm_out.record_gcc_switches_section, - SECTION_DEBUG - | SECTION_MERGE - | SECTION_STRINGS - | (SECTION_ENTSIZE & 1), - NULL); - switch_to_section (sec); - started = true; - } - } - - default: - break; - } - - /* The return value is currently ignored by the caller, but must be 0. - For -fverbose-asm the return value would be the number of characters - emitted into the assembler file. */ - return 0; + section *sec = get_section (targetm.asm_out.record_gcc_switches_section, + SECTION_DEBUG | SECTION_MERGE + | SECTION_STRINGS | (SECTION_ENTSIZE & 1), NULL); + switch_to_section (sec); + ASM_OUTPUT_ASCII (asm_out_file, options, strlen (options) + 1); } /* Emit text to declare externally defined symbols. It is needed to -- 2.29.2