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},
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<const char *> 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. */
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);
#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);
return NULL;
}
+/* Return a heap allocated producer with command line options. */
+
+char *
+gen_command_line_string (cl_decoded_option *options,
+ unsigned int options_count)
+{
+ auto_vec<const char *> switches;
+ char *options_string, *tail;
+ const char *p;
+ size_t len = 0;
+
+ for (unsigned i = 0; i < options_count; i++)
+ switch (options[i].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[i].opt_index].flags
+ & CL_NO_DWARF_RECORD)
+ continue;
+ gcc_checking_assert (options[i].canonical_option[0][0] == '-');
+ switch (options[i].canonical_option[0][1])
+ {
+ case 'M':
+ case 'i':
+ case 'W':
+ continue;
+ case 'f':
+ if (strncmp (options[i].canonical_option[0] + 2,
+ "dump", 4) == 0)
+ continue;
+ break;
+ default:
+ break;
+ }
+ switches.safe_push (options[i].orig_option_with_args_text);
+ len += strlen (options[i].orig_option_with_args_text) + 1;
+ break;
+ }
+
+ options_string = XNEWVEC (char, len + 1);
+ tail = options_string;
+
+ unsigned i;
+ FOR_EACH_VEC_ELT (switches, i, p)
+ {
+ len = strlen (p);
+ memcpy (tail, p, len);
+ tail += len;
+ if (i != switches.length () - 1)
+ {
+ *tail = ' ';
+ ++tail;
+ }
+ }
+
+ *tail = '\0';
+ return options_string;
+}
+
+/* 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)
+{
+ return concat (language_string, " ", version_string, " ",
+ gen_command_line_string (options, options_count), NULL);
+}
+
#if CHECKING_P
namespace selftest {
extern void prepend_xassembler_to_collect_as_options (const char *, obstack *);
+extern char *gen_command_line_string (cl_decoded_option *options,
+ unsigned int options_count);
+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) \
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\
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
#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. */
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
/* 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;
}
}
-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
{
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,
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);
+ fputs (" options passed: ", asm_out_file);
+ fputs (gen_command_line_string (save_decoded_options,
+ save_decoded_options_count),
+ asm_out_file);
+ fputc ('\n', asm_out_file);
}
}
}
if (version_flag)
{
print_version (stderr, "", true);
- if (! quiet_flag)
- print_switch_values (print_to_stderr);
+ if (!quiet_flag)
+ {
+ fputs ("options passed: ", stderr);
+ fputs (gen_command_line_string (save_decoded_options,
+ save_decoded_options_count), stderr);
+ fputc ('\n', stderr);
+ }
}
if (flag_syntax_only)
#include "fold-const.h"
#include "stor-layout.h"
#include "varasm.h"
+#include "version.h"
#include "flags.h"
#include "stmt.h"
#include "expr.h"
#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. */
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