X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fgcc.c;h=c2998bd96b8392dd317730c586c4e3450c308676;hb=e7a960245cbc9ed81b426a79876e0a84a59bcea1;hp=82ddc1620d28c281ffc0c985bcb075e7f05fdfd4;hpb=f83b64ca5fdab1eb0ddbd4266d7105b81b5294ec;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/gcc.c b/gcc/gcc.c index 82ddc1620d2..c2998bd96b8 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -47,6 +47,7 @@ compilation is specified by a string called a "spec". */ #include "diagnostic.h" #include "flags.h" #include "opts.h" +#include "vec.h" #ifdef HAVE_MMAP_FILE # include @@ -114,10 +115,6 @@ static int print_help_list; static int print_version; -/* Flag indicating whether we should print the command and arguments */ - -static int verbose_flag; - /* Flag indicating whether we should ONLY print the command and arguments (like verbose_flag) without executing the command. Displayed arguments are quoted so that the generated command @@ -287,6 +284,7 @@ static const char *print_asm_header_spec_function (int, const char **); static const char *compare_debug_dump_opt_spec_function (int, const char **); static const char *compare_debug_self_opt_spec_function (int, const char **); static const char *compare_debug_auxbase_opt_spec_function (int, const char **); +static const char *pass_through_libs_spec_func (int, const char **); /* The Specs Language @@ -649,7 +647,7 @@ proper position among the other output files. */ /* We want %{T*} after %{L*} and %D so that it can be used to specify linker scripts which exist in user specified directories, or in standard directories. */ -/* We pass any -flto and -fwhopr flags on to the linker, which is expected +/* We pass any -flto flags on to the linker, which is expected to understand them. In practice, this means it had better be collect2. */ #ifndef LINK_COMMAND_SPEC #define LINK_COMMAND_SPEC "\ @@ -659,13 +657,12 @@ proper position among the other output files. */ -plugin %(linker_plugin_file) \ -plugin-opt=%(lto_wrapper) \ -plugin-opt=-fresolution=%u.res \ - %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)} \ - %{static:-plugin-opt=-pass-through=-lc} \ + %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \ } \ - %{flto:%opt_index; const char *arg = decoded->arg; @@ -3166,6 +3129,8 @@ driver_handle_option (struct gcc_options *opts, gcc_assert (opts == &global_options); gcc_assert (opts_set == &global_options_set); gcc_assert (kind == DK_UNSPECIFIED); + gcc_assert (loc == UNKNOWN_LOCATION); + gcc_assert (dc == global_dc); switch (opt_index) { @@ -3430,7 +3395,7 @@ driver_handle_option (struct gcc_options *opts, is intended for use in shell scripts to capture the driver-generated command line. */ verbose_only_flag++; - verbose_flag++; + verbose_flag = 1; do_save = false; break; @@ -3465,10 +3430,6 @@ driver_handle_option (struct gcc_options *opts, validated = true; break; - case OPT_v: /* Print our subcommands and print versions. */ - verbose_flag++; - break; - case OPT_x: spec_lang = arg; if (!strcmp (spec_lang, "none")) @@ -3517,6 +3478,19 @@ driver_handle_option (struct gcc_options *opts, return true; } +/* Put the driver's standard set of option handlers in *HANDLERS. */ + +static void +set_option_handlers (struct cl_option_handlers *handlers) +{ + handlers->unknown_option_callback = driver_unknown_option_callback; + handlers->wrong_lang_callback = driver_wrong_lang_callback; + handlers->post_handling_callback = driver_post_handling_callback; + handlers->num_handlers = 1; + handlers->handlers[0].handler = driver_handle_option; + handlers->handlers[0].mask = CL_DRIVER; +} + /* Create the vector `switches' and its contents. Store its length in `n_switches'. */ @@ -3741,12 +3715,7 @@ process_command (unsigned int decoded_options_count, last_language_n_infiles = -1; - handlers.unknown_option_callback = driver_unknown_option_callback; - handlers.wrong_lang_callback = driver_wrong_lang_callback; - handlers.post_handling_callback = driver_post_handling_callback; - handlers.num_handlers = 1; - handlers.handlers[0].handler = driver_handle_option; - handlers.handlers[0].mask = CL_DRIVER; + set_option_handlers (&handlers); for (j = 1; j < decoded_options_count; j++) { @@ -3806,7 +3775,8 @@ process_command (unsigned int decoded_options_count, } read_cmdline_option (&global_options, &global_options_set, - decoded_options + j, CL_DRIVER, &handlers); + decoded_options + j, UNKNOWN_LOCATION, + CL_DRIVER, &handlers, global_dc); } /* If -save-temps=obj and -o name, create the prefix to use for %b. @@ -4108,6 +4078,7 @@ insert_wrapper (const char *wrapper) int i; char *buf = xstrdup (wrapper); char *p = buf; + unsigned int old_length = VEC_length (const_char_p, argbuf); do { @@ -4117,15 +4088,10 @@ insert_wrapper (const char *wrapper) } while ((p = strchr (p, ',')) != NULL); - if (argbuf_index + n >= argbuf_length) - { - argbuf_length = argbuf_length * 2; - while (argbuf_length < argbuf_index + n) - argbuf_length *= 2; - argbuf = XRESIZEVEC (const char *, argbuf, argbuf_length); - } - for (i = argbuf_index - 1; i >= 0; i--) - argbuf[i + n] = argbuf[i]; + VEC_safe_grow (const_char_p, heap, argbuf, old_length + n); + memmove (VEC_address (const_char_p, argbuf) + n, + VEC_address (const_char_p, argbuf), + old_length * sizeof (const_char_p)); i = 0; p = buf; @@ -4136,11 +4102,11 @@ insert_wrapper (const char *wrapper) *p = 0; p++; } - argbuf[i++] = p; + VEC_replace (const_char_p, argbuf, i, p); + i++; } while ((p = strchr (p, ',')) != NULL); gcc_assert (i == n); - argbuf_index += n; } /* Process the spec SPEC and run the commands specified therein. @@ -4157,12 +4123,13 @@ do_spec (const char *spec) If -pipe, this forces out the last command if it ended in `|'. */ if (value == 0) { - if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) - argbuf_index--; + if (VEC_length (const_char_p, argbuf) > 0 + && !strcmp (VEC_last (const_char_p, argbuf), "|")) + VEC_pop (const_char_p, argbuf); set_collect_gcc_options (); - if (argbuf_index > 0) + if (VEC_length (const_char_p, argbuf) > 0) value = execute (); } @@ -4258,68 +4225,64 @@ do_self_spec (const char *spec) if ((switches[i].live_cond & SWITCH_IGNORE)) switches[i].live_cond |= SWITCH_IGNORE_PERMANENTLY; - if (argbuf_index > 0) + if (VEC_length (const_char_p, argbuf) > 0) { - switches = XRESIZEVEC (struct switchstr, switches, - n_switches + argbuf_index + 1); - - for (i = 0; i < argbuf_index; i++) + const char **argbuf_copy; + struct cl_decoded_option *decoded_options; + struct cl_option_handlers handlers; + unsigned int decoded_options_count; + unsigned int j; + + /* Create a copy of argbuf with a dummy argv[0] entry for + decode_cmdline_options_to_array. */ + argbuf_copy = XNEWVEC (const char *, + VEC_length (const_char_p, argbuf) + 1); + argbuf_copy[0] = ""; + memcpy (argbuf_copy + 1, VEC_address (const_char_p, argbuf), + VEC_length (const_char_p, argbuf) * sizeof (const char *)); + + decode_cmdline_options_to_array (VEC_length (const_char_p, argbuf) + 1, + argbuf_copy, + CL_DRIVER, &decoded_options, + &decoded_options_count); + + set_option_handlers (&handlers); + + for (j = 1; j < decoded_options_count; j++) { - struct switchstr *sw; - const char *p = argbuf[i]; - int c = *p; - - /* Each switch should start with '-'. */ - if (c != '-') - fatal_error ("switch %qs does not start with %<-%>", argbuf[i]); - - p++; - c = *p; - - sw = &switches[n_switches++]; - sw->part1 = p; - sw->live_cond = 0; - sw->validated = 0; - sw->ordering = 0; - - /* Deal with option arguments in separate argv elements. */ - if ((SWITCH_TAKES_ARG (c) > (p[1] != 0)) - || WORD_SWITCH_TAKES_ARG (p)) + switch (decoded_options[j].opt_index) { - int j = 0; - int n_args = WORD_SWITCH_TAKES_ARG (p); + case OPT_SPECIAL_input_file: + /* Specs should only generate options, not input + files. */ + if (strcmp (decoded_options[j].arg, "-") != 0) + fatal_error ("switch %qs does not start with %<-%>", + decoded_options[j].arg); + else + fatal_error ("spec-generated switch is just %<-%>"); + break; - if (n_args == 0) - { - /* Count only the option arguments in separate argv elements. */ - n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0); - } - if (i + n_args >= argbuf_index) - fatal_error ("argument to %<-%s%> is missing", p); - sw->args - = XNEWVEC (const char *, n_args + 1); - while (j < n_args) - sw->args[j++] = argbuf[++i]; - /* Null-terminate the vector. */ - sw->args[j] = 0; - } - else if (c == 'o') - { - /* On some systems, ld cannot handle "-o" without - a space. So split the option from its argument. */ - char *part1 = XNEWVEC (char, 2); - part1[0] = c; - part1[1] = '\0'; - - sw->part1 = part1; - sw->args = XNEWVEC (const char *, 2); - sw->args[0] = xstrdup (p+1); - sw->args[1] = 0; + case OPT_fcompare_debug_second: + case OPT_fcompare_debug: + case OPT_fcompare_debug_: + case OPT_o: + /* Avoid duplicate processing of some options from + compare-debug specs; just save them here. */ + save_switch (decoded_options[j].canonical_option[0], + (decoded_options[j].canonical_option_num_elements + - 1), + &decoded_options[j].canonical_option[1], false); + break; + + default: + read_cmdline_option (&global_options, &global_options_set, + decoded_options + j, UNKNOWN_LOCATION, + CL_DRIVER, &handlers, global_dc); + break; } - else - sw->args = 0; } + alloc_switch (); switches[n_switches].part1 = 0; } } @@ -4418,6 +4381,22 @@ compile_input_file_p (struct infile *infile) return false; } +/* Process each member of VEC as a spec. */ + +static void +do_specs_vec (VEC(char_p,heap) *vec) +{ + unsigned ix; + char *opt; + + FOR_EACH_VEC_ELT (char_p, vec, ix, opt) + { + do_spec_1 (opt, 1, NULL); + /* Make each accumulated option a separate argument. */ + do_spec_1 (" ", 0, NULL); + } +} + /* Process the sub-spec SPEC as a portion of a larger spec. This is like processing a whole spec except that we do not initialize at the beginning and we do not supply a @@ -4446,7 +4425,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) case '\n': end_going_arg (); - if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) + if (VEC_length (const_char_p, argbuf) > 0 + && !strcmp (VEC_last (const_char_p, argbuf), "|")) { /* A `|' before the newline means use a pipe here, but only if -pipe was specified. @@ -4457,12 +4437,12 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) break; } else - argbuf_index--; + VEC_pop (const_char_p, argbuf); } set_collect_gcc_options (); - if (argbuf_index > 0) + if (VEC_length (const_char_p, argbuf) > 0) { value = execute (); if (value) @@ -4958,7 +4938,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) case 'W': { - int cur_index = argbuf_index; + unsigned int cur_index = VEC_length (const_char_p, argbuf); /* Handle the {...} following the %W. */ if (*p != '{') fatal_error ("spec %qs has invalid %<%%W%c%>", spec, *p); @@ -4968,8 +4948,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) end_going_arg (); /* If any args were output, mark the last one for deletion on failure. */ - if (argbuf_index != cur_index) - record_temp_file (argbuf[argbuf_index - 1], 0, 1); + if (VEC_length (const_char_p, argbuf) != cur_index) + record_temp_file (VEC_last (const_char_p, argbuf), 0, 1); break; } @@ -4978,6 +4958,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) { const char *p1 = p; char *string; + char *opt; + unsigned ix; /* Skip past the option value and make a copy. */ if (*p != '{') @@ -4987,8 +4969,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) string = save_string (p1 + 1, p - p1 - 2); /* See if we already recorded this option. */ - for (i = 0; i < n_linker_options; i++) - if (! strcmp (string, linker_options[i])) + FOR_EACH_VEC_ELT (char_p, linker_options, ix, opt) + if (! strcmp (string, opt)) { free (string); return 0; @@ -5001,32 +4983,17 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) /* Dump out the options accumulated previously using %x. */ case 'X': - for (i = 0; i < n_linker_options; i++) - { - do_spec_1 (linker_options[i], 1, NULL); - /* Make each accumulated option a separate argument. */ - do_spec_1 (" ", 0, NULL); - } + do_specs_vec (linker_options); break; /* Dump out the options accumulated previously using -Wa,. */ case 'Y': - for (i = 0; i < n_assembler_options; i++) - { - do_spec_1 (assembler_options[i], 1, NULL); - /* Make each accumulated option a separate argument. */ - do_spec_1 (" ", 0, NULL); - } + do_specs_vec (assembler_options); break; /* Dump out the options accumulated previously using -Wp,. */ case 'Z': - for (i = 0; i < n_preprocessor_options; i++) - { - do_spec_1 (preprocessor_options[i], 1, NULL); - /* Make each accumulated option a separate argument. */ - do_spec_1 (" ", 0, NULL); - } + do_specs_vec (preprocessor_options); break; /* Here are digits and numbers that just process @@ -5313,9 +5280,7 @@ eval_spec_function (const char *func, const char *args) const char *funcval; /* Saved spec processing context. */ - int save_argbuf_index; - int save_argbuf_length; - const char **save_argbuf; + VEC(const_char_p,heap) *save_argbuf; int save_arg_going; int save_delete_this_arg; @@ -5331,8 +5296,6 @@ eval_spec_function (const char *func, const char *args) fatal_error ("unknown spec function %qs", func); /* Push the spec processing context. */ - save_argbuf_index = argbuf_index; - save_argbuf_length = argbuf_length; save_argbuf = argbuf; save_arg_going = arg_going; @@ -5353,12 +5316,11 @@ eval_spec_function (const char *func, const char *args) /* argbuf_index is an index for the next argument to be inserted, and so contains the count of the args already inserted. */ - funcval = (*sf->func) (argbuf_index, argbuf); + funcval = (*sf->func) (VEC_length (const_char_p, argbuf), + VEC_address (const_char_p, argbuf)); /* Pop the spec processing context. */ - argbuf_index = save_argbuf_index; - argbuf_length = save_argbuf_length; - free (argbuf); + VEC_free (const_char_p, heap, argbuf); argbuf = save_argbuf; arg_going = save_arg_going; @@ -6111,6 +6073,7 @@ main (int argc, char **argv) int num_linker_inputs = 0; char *explicit_link_files; char *specs_file; + char *lto_wrapper_file; const char *p; struct user_specs *uptr; char **old_argv = argv; @@ -6134,6 +6097,8 @@ main (int argc, char **argv) if (argv != old_argv) at_file_supplied = true; + global_options = global_options_init; + decode_cmdline_options_to_array (argc, CONST_CAST2 (const char **, char **, argv), CL_DRIVER, @@ -6279,14 +6244,17 @@ main (int argc, char **argv) if (!compare_debug_second) { n_switches_debug_check[1] = n_switches; + n_switches_alloc_debug_check[1] = n_switches_alloc; switches_debug_check[1] = XDUPVEC (struct switchstr, switches, - n_switches + 1); + n_switches_alloc); do_self_spec ("%:compare-debug-self-opt()"); n_switches_debug_check[0] = n_switches; + n_switches_alloc_debug_check[0] = n_switches_alloc; switches_debug_check[0] = switches; n_switches = n_switches_debug_check[1]; + n_switches_alloc = n_switches_alloc_debug_check[1]; switches = switches_debug_check[1]; } @@ -6302,9 +6270,11 @@ main (int argc, char **argv) if (!compare_debug_second) { n_switches_debug_check[1] = n_switches; + n_switches_alloc_debug_check[1] = n_switches_alloc; switches_debug_check[1] = switches; compare_debug = -compare_debug; n_switches = n_switches_debug_check[0]; + n_switches_alloc = n_switches_debug_check[0]; switches = switches_debug_check[0]; } } @@ -6324,10 +6294,10 @@ main (int argc, char **argv) if (*sysroot_suffix_spec != 0 && do_spec_2 (sysroot_suffix_spec) == 0) { - if (argbuf_index > 1) + if (VEC_length (const_char_p, argbuf) > 1) error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC"); - else if (argbuf_index == 1) - target_sysroot_suffix = xstrdup (argbuf[argbuf_index -1]); + else if (VEC_length (const_char_p, argbuf) == 1) + target_sysroot_suffix = xstrdup (VEC_last (const_char_p, argbuf)); } #ifdef HAVE_LD_SYSROOT @@ -6347,10 +6317,10 @@ main (int argc, char **argv) if (*sysroot_hdrs_suffix_spec != 0 && do_spec_2 (sysroot_hdrs_suffix_spec) == 0) { - if (argbuf_index > 1) + if (VEC_length (const_char_p, argbuf) > 1) error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC"); - else if (argbuf_index == 1) - target_sysroot_hdrs_suffix = xstrdup (argbuf[argbuf_index -1]); + else if (VEC_length (const_char_p, argbuf) == 1) + target_sysroot_hdrs_suffix = xstrdup (VEC_last (const_char_p, argbuf)); } /* Look for startfiles in the standard places. */ @@ -6358,9 +6328,10 @@ main (int argc, char **argv) && do_spec_2 (startfile_prefix_spec) == 0 && do_spec_1 (" ", 0, NULL) == 0) { + const char *arg; int ndx; - for (ndx = 0; ndx < argbuf_index; ndx++) - add_sysrooted_prefix (&startfile_prefixes, argbuf[ndx], "BINUTILS", + FOR_EACH_VEC_ELT (const_char_p, argbuf, ndx, arg) + add_sysrooted_prefix (&startfile_prefixes, arg, "BINUTILS", PREFIX_PRIORITY_LAST, 0, 1); } /* We should eventually get rid of all these and stick to @@ -6441,9 +6412,10 @@ main (int argc, char **argv) /* Set up to remember the pathname of the lto wrapper. */ - lto_wrapper_spec = find_a_file (&exec_prefixes, "lto-wrapper", X_OK, false); - if (lto_wrapper_spec) + lto_wrapper_file = find_a_file (&exec_prefixes, "lto-wrapper", X_OK, false); + if (lto_wrapper_file) { + lto_wrapper_spec = lto_wrapper_file; obstack_init (&collect_obstack); obstack_grow (&collect_obstack, "COLLECT_LTO_WRAPPER=", sizeof ("COLLECT_LTO_WRAPPER=") - 1); @@ -6720,12 +6692,14 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" compare_debug = -compare_debug; n_switches = n_switches_debug_check[1]; + n_switches_alloc = n_switches_alloc_debug_check[1]; switches = switches_debug_check[1]; value = do_spec (input_file_compiler->spec); compare_debug = -compare_debug; n_switches = n_switches_debug_check[0]; + n_switches_alloc = n_switches_alloc_debug_check[0]; switches = switches_debug_check[0]; if (value < 0) @@ -6826,15 +6800,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" fuse_linker_plugin + strlen (fuse_linker_plugin), 0)) { linker_plugin_file_spec = find_a_file (&exec_prefixes, - "liblto_plugin.so", R_OK, + LTOPLUGINSONAME, R_OK, false); if (!linker_plugin_file_spec) - fatal_error ("-fuse-linker-plugin, but liblto_plugin.so not found"); - - lto_libgcc_spec = find_a_file (&startfile_prefixes, "libgcc.a", - R_OK, true); - if (!lto_libgcc_spec) - fatal_error ("could not find libgcc.a"); + fatal_error ("-fuse-linker-plugin, but " LTOPLUGINSONAME " not found"); } lto_gcc_spec = argv[0]; @@ -8089,19 +8058,20 @@ compare_debug_dump_opt_spec_function (int arg, do_spec_2 ("%{fdump-final-insns=*:%*}"); do_spec_1 (" ", 0, NULL); - if (argbuf_index > 0 && strcmp (argv[argbuf_index - 1], ".")) + if (VEC_length (const_char_p, argbuf) > 0 + && strcmp (argv[VEC_length (const_char_p, argbuf) - 1], ".")) { if (!compare_debug) return NULL; - name = xstrdup (argv[argbuf_index - 1]); + name = xstrdup (argv[VEC_length (const_char_p, argbuf) - 1]); ret = NULL; } else { const char *ext = NULL; - if (argbuf_index > 0) + if (VEC_length (const_char_p, argbuf) > 0) { do_spec_2 ("%{o*:%*}%{!o:%{!S:%b%O}%{S:%b.s}}"); ext = ".gkd"; @@ -8113,9 +8083,9 @@ compare_debug_dump_opt_spec_function (int arg, do_spec_1 (" ", 0, NULL); - gcc_assert (argbuf_index > 0); + gcc_assert (VEC_length (const_char_p, argbuf) > 0); - name = concat (argbuf[argbuf_index - 1], ext, NULL); + name = concat (VEC_last (const_char_p, argbuf), ext, NULL); ret = concat ("-fdump-final-insns=", name, NULL); } @@ -8159,9 +8129,9 @@ compare_debug_self_opt_spec_function (int arg, do_spec_2 ("%{c|S:%{o*:%*}}"); do_spec_1 (" ", 0, NULL); - if (argbuf_index > 0) + if (VEC_length (const_char_p, argbuf) > 0) debug_auxbase_opt = concat ("-auxbase-strip ", - argbuf[argbuf_index - 1], + VEC_last (const_char_p, argbuf), NULL); else debug_auxbase_opt = NULL; @@ -8214,3 +8184,46 @@ compare_debug_auxbase_opt_spec_function (int arg, return name; } + +/* %:pass-through-libs spec function. Finds all -l options and input + file names in the lib spec passed to it, and makes a list of them + prepended with the plugin option to cause them to be passed through + to the final link after all the new object files have been added. */ + +const char * +pass_through_libs_spec_func (int argc, const char **argv) +{ + char *prepended = xstrdup (" "); + int n; + /* Shlemiel the painter's algorithm. Innately horrible, but at least + we know that there will never be more than a handful of strings to + concat, and it's only once per run, so it's not worth optimising. */ + for (n = 0; n < argc; n++) + { + char *old = prepended; + /* Anything that isn't an option is a full path to an output + file; pass it through if it ends in '.a'. Among options, + pass only -l. */ + if (argv[n][0] == '-' && argv[n][1] == 'l') + { + const char *lopt = argv[n] + 2; + /* Handle both joined and non-joined -l options. If for any + reason there's a trailing -l with no joined or following + arg just discard it. */ + if (!*lopt && ++n >= argc) + break; + else if (!*lopt) + lopt = argv[n]; + prepended = concat (prepended, "-plugin-opt=-pass-through=-l", + lopt, " ", NULL); + } + else if (!strcmp (".a", argv[n] + strlen (argv[n]) - 2)) + { + prepended = concat (prepended, "-plugin-opt=-pass-through=", + argv[n], " ", NULL); + } + if (prepended != old) + free (old); + } + return prepended; +}