Commit 742a072a by David Malcolm Committed by David Malcolm

gcc.c: Split up the driver's "main" into smaller functions

gcc/ChangeLog:
	* gcc.c (class driver): New class.
	(main): Reimplement in terms of driver::main, moving most of the
	locals to be locals within individual methods of class driver.
	The remaining locals "explicit_link_files", "decoded_options" and
	"decoded_options_count" are used by multiple driver:: methods, and
	so become member data.  Doing so isolates the argc/argv reads and
	writes.  Replace "goto out" with a special exit code from
	new method driver::prepare_infiles.  Split out the old
	implementation of main into the following...
	(driver::main): New function, corresponding to the old "main"
	implementation.
	(driver::set_progname): New function, taken from the old
	"main" implementation.
	(driver::expand_at_files): Likewise.
	(driver::decode_argv): Likewise.
	(driver::global_initializations): Likewise.
	(driver::build_multilib_strings): Likewise.
	(driver::set_up_specs): Likewise.
	(driver::putenv_COLLECT_GCC): Likewise.
	(driver::maybe_putenv_COLLECT_LTO_WRAPPER): Likewise.
	(driver::handle_unrecognized_options): Likewise.
	(driver::maybe_print_and_exit): Likewise.
	(driver::prepare_infiles): Likewise.
	(driver::do_spec_on_infiles): Likewise.
	(driver::maybe_run_linker): Likewise.
	(driver::final_actions): Likewise.
	(driver::get_exit_code): Likewise.

From-SVN: r215861
parent 2bd8ca21
2014-10-03 David Malcolm <dmalcolm@redhat.com>
* gcc.c (class driver): New class.
(main): Reimplement in terms of driver::main, moving most of the
locals to be locals within individual methods of class driver.
The remaining locals "explicit_link_files", "decoded_options" and
"decoded_options_count" are used by multiple driver:: methods, and
so become member data. Doing so isolates the argc/argv reads and
writes. Replace "goto out" with a special exit code from
new method driver::prepare_infiles. Split out the old
implementation of main into the following...
(driver::main): New function, corresponding to the old "main"
implementation.
(driver::set_progname): New function, taken from the old
"main" implementation.
(driver::expand_at_files): Likewise.
(driver::decode_argv): Likewise.
(driver::global_initializations): Likewise.
(driver::build_multilib_strings): Likewise.
(driver::set_up_specs): Likewise.
(driver::putenv_COLLECT_GCC): Likewise.
(driver::maybe_putenv_COLLECT_LTO_WRAPPER): Likewise.
(driver::handle_unrecognized_options): Likewise.
(driver::maybe_print_and_exit): Likewise.
(driver::prepare_infiles): Likewise.
(driver::do_spec_on_infiles): Likewise.
(driver::maybe_run_linker): Likewise.
(driver::final_actions): Likewise.
(driver::get_exit_code): Likewise.
2014-10-03 Yury Gribov <y.gribov@samsung.com> 2014-10-03 Yury Gribov <y.gribov@samsung.com>
* asan.c (asan_finish_file): Disable __asan_init calls for KASan; * asan.c (asan_finish_file): Disable __asan_init calls for KASan;
...@@ -6724,49 +6724,132 @@ compare_files (char *cmpfile[]) ...@@ -6724,49 +6724,132 @@ compare_files (char *cmpfile[])
return ret; return ret;
} }
extern int main (int, char **); /* The top-level "main" within the driver would be ~1000 lines long.
This class breaks it up into smaller functions and contains some
state shared by them. */
int class driver
main (int argc, char **argv)
{ {
size_t i; public:
int value; int main (int argc, char **argv);
int linker_was_run = 0;
int lang_n_infiles = 0; private:
int num_linker_inputs = 0; void set_progname (const char *argv0) const;
void expand_at_files (int *argc, char ***argv) const;
void decode_argv (int argc, const char **argv);
void global_initializations () const;
void build_multilib_strings () const;
void set_up_specs () const;
void putenv_COLLECT_GCC (const char *argv0) const;
void maybe_putenv_COLLECT_LTO_WRAPPER () const;
void handle_unrecognized_options () const;
int maybe_print_and_exit () const;
bool prepare_infiles ();
void do_spec_on_infiles () const;
void maybe_run_linker (const char *argv0) const;
void final_actions () const;
int get_exit_code () const;
private:
char *explicit_link_files; char *explicit_link_files;
char *specs_file;
char *lto_wrapper_file;
const char *p;
struct user_specs *uptr;
char **old_argv = argv;
struct cl_decoded_option *decoded_options; struct cl_decoded_option *decoded_options;
unsigned int decoded_options_count; unsigned int decoded_options_count;
};
/* Implement the top-level "main" within the driver in terms of
driver::main. */
extern int main (int, char **);
int
main (int argc, char **argv)
{
driver d;
return d.main (argc, argv);
}
/* driver::main is implemented as a series of driver:: method calls. */
int
driver::main (int argc, char **argv)
{
bool early_exit;
set_progname (argv[0]);
expand_at_files (&argc, &argv);
decode_argv (argc, const_cast <const char **> (argv));
global_initializations ();
build_multilib_strings ();
set_up_specs ();
putenv_COLLECT_GCC (argv[0]);
maybe_putenv_COLLECT_LTO_WRAPPER ();
handle_unrecognized_options ();
if (!maybe_print_and_exit ())
return 0;
early_exit = prepare_infiles ();
if (early_exit)
return get_exit_code ();
do_spec_on_infiles ();
maybe_run_linker (argv[0]);
final_actions ();
return get_exit_code ();
}
/* Locate the final component of argv[0] after any leading path, and set
the program name accordingly. */
p = argv[0] + strlen (argv[0]); void
while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) driver::set_progname (const char *argv0) const
{
const char *p = argv0 + strlen (argv0);
while (p != argv0 && !IS_DIR_SEPARATOR (p[-1]))
--p; --p;
progname = p; progname = p;
xmalloc_set_program_name (progname); xmalloc_set_program_name (progname);
}
/* Expand any @ files within the command-line args,
setting at_file_supplied if any were expanded. */
void
driver::expand_at_files (int *argc, char ***argv) const
{
char **old_argv = *argv;
expandargv (&argc, &argv); expandargv (argc, argv);
/* Determine if any expansions were made. */ /* Determine if any expansions were made. */
if (argv != old_argv) if (*argv != old_argv)
at_file_supplied = true; at_file_supplied = true;
}
/* Decode the command-line arguments from argc/argv into the
decoded_options array. */
void
driver::decode_argv (int argc, const char **argv)
{
/* Register the language-independent parameters. */ /* Register the language-independent parameters. */
global_init_params (); global_init_params ();
finish_params (); finish_params ();
init_options_struct (&global_options, &global_options_set); init_options_struct (&global_options, &global_options_set);
decode_cmdline_options_to_array (argc, CONST_CAST2 (const char **, char **, decode_cmdline_options_to_array (argc, argv,
argv),
CL_DRIVER, CL_DRIVER,
&decoded_options, &decoded_options_count); &decoded_options, &decoded_options_count);
}
/* Perform various initializations and setup. */
void
driver::global_initializations () const
{
/* Unlock the stdio streams. */ /* Unlock the stdio streams. */
unlock_std_streams (); unlock_std_streams ();
...@@ -6808,10 +6891,16 @@ main (int argc, char **argv) ...@@ -6808,10 +6891,16 @@ main (int argc, char **argv)
alloc_args (); alloc_args ();
obstack_init (&obstack); obstack_init (&obstack);
}
/* Build multilib_select, et. al from the separate lines that make up each /* Build multilib_select, et. al from the separate lines that make up each
multilib selection. */ multilib selection. */
void
driver::build_multilib_strings () const
{
{ {
const char *p;
const char *const *q = multilib_raw; const char *const *q = multilib_raw;
int need_space; int need_space;
...@@ -6844,7 +6933,7 @@ main (int argc, char **argv) ...@@ -6844,7 +6933,7 @@ main (int argc, char **argv)
multilib_reuse = XOBFINISH (&multilib_obstack, const char *); multilib_reuse = XOBFINISH (&multilib_obstack, const char *);
need_space = FALSE; need_space = FALSE;
for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++) for (size_t i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
{ {
if (need_space) if (need_space)
obstack_1grow (&multilib_obstack, ' '); obstack_1grow (&multilib_obstack, ' ');
...@@ -6857,6 +6946,15 @@ main (int argc, char **argv) ...@@ -6857,6 +6946,15 @@ main (int argc, char **argv)
obstack_1grow (&multilib_obstack, 0); obstack_1grow (&multilib_obstack, 0);
multilib_defaults = XOBFINISH (&multilib_obstack, const char *); multilib_defaults = XOBFINISH (&multilib_obstack, const char *);
} }
}
/* Set up the spec-handling machinery. */
void
driver::set_up_specs () const
{
char *specs_file;
size_t i;
#ifdef INIT_ENVIRONMENT #ifdef INIT_ENVIRONMENT
/* Set up any other necessary machine specific environment variables. */ /* Set up any other necessary machine specific environment variables. */
...@@ -7016,7 +7114,7 @@ main (int argc, char **argv) ...@@ -7016,7 +7114,7 @@ main (int argc, char **argv)
/* Process any user specified specs in the order given on the command /* Process any user specified specs in the order given on the command
line. */ line. */
for (uptr = user_specs_head; uptr; uptr = uptr->next) for (struct user_specs *uptr = user_specs_head; uptr; uptr = uptr->next)
{ {
char *filename = find_a_file (&startfile_prefixes, uptr->filename, char *filename = find_a_file (&startfile_prefixes, uptr->filename,
R_OK, true); R_OK, true);
...@@ -7088,16 +7186,27 @@ main (int argc, char **argv) ...@@ -7088,16 +7186,27 @@ main (int argc, char **argv)
/* Now that we have the switches and the specs, set /* Now that we have the switches and the specs, set
the subdirectory based on the options. */ the subdirectory based on the options. */
set_multilib_dir (); set_multilib_dir ();
}
/* Set up to remember the pathname of gcc and any options /* Set up to remember the pathname of gcc and any options
needed for collect. We use argv[0] instead of progname because needed for collect. We use argv[0] instead of progname because
we need the complete pathname. */ we need the complete pathname. */
void
driver::putenv_COLLECT_GCC (const char *argv0) const
{
obstack_init (&collect_obstack); obstack_init (&collect_obstack);
obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1); obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1); obstack_grow (&collect_obstack, argv0, strlen (argv0) + 1);
xputenv (XOBFINISH (&collect_obstack, char *)); xputenv (XOBFINISH (&collect_obstack, char *));
}
/* Set up to remember the pathname of the lto wrapper. */ /* Set up to remember the pathname of the lto wrapper. */
void
driver::maybe_putenv_COLLECT_LTO_WRAPPER () const
{
char *lto_wrapper_file;
if (have_c) if (have_c)
lto_wrapper_file = NULL; lto_wrapper_file = NULL;
...@@ -7116,14 +7225,24 @@ main (int argc, char **argv) ...@@ -7116,14 +7225,24 @@ main (int argc, char **argv)
xputenv (XOBFINISH (&collect_obstack, char *)); xputenv (XOBFINISH (&collect_obstack, char *));
} }
/* Reject switches that no pass was interested in. */ }
for (i = 0; (int) i < n_switches; i++) /* Reject switches that no pass was interested in. */
void
driver::handle_unrecognized_options () const
{
for (size_t i = 0; (int) i < n_switches; i++)
if (! switches[i].validated) if (! switches[i].validated)
error ("unrecognized command line option %<-%s%>", switches[i].part1); error ("unrecognized command line option %<-%s%>", switches[i].part1);
}
/* Obey some of the options. */ /* Handle the various -print-* options, returning 0 if the driver
should exit, or nonzero if the driver should continue. */
int
driver::maybe_print_and_exit () const
{
if (print_search_dirs) if (print_search_dirs)
{ {
printf (_("install: %s%s\n"), printf (_("install: %s%s\n"),
...@@ -7286,11 +7405,24 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" ...@@ -7286,11 +7405,24 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
return (0); return (0);
} }
return 1;
}
/* Figure out what to do with each input file.
Return true if we need to exit early from "main", false otherwise. */
bool
driver::prepare_infiles ()
{
size_t i;
int lang_n_infiles = 0;
if (n_infiles == added_libraries) if (n_infiles == added_libraries)
fatal_error ("no input files"); fatal_error ("no input files");
if (seen_error ()) if (seen_error ())
goto out; /* Early exit needed from main. */
return true;
/* Make a place to record the compiler output file names /* Make a place to record the compiler output file names
that correspond to the input files. */ that correspond to the input files. */
...@@ -7338,6 +7470,17 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" ...@@ -7338,6 +7470,17 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
if (!combine_inputs && have_c && have_o && lang_n_infiles > 1) if (!combine_inputs && have_c && have_o && lang_n_infiles > 1)
fatal_error ("cannot specify -o with -c, -S or -E with multiple files"); fatal_error ("cannot specify -o with -c, -S or -E with multiple files");
/* No early exit needed from main; we can continue. */
return false;
}
/* Run the spec machinery on each input file. */
void
driver::do_spec_on_infiles () const
{
size_t i;
for (i = 0; (int) i < n_infiles; i++) for (i = 0; (int) i < n_infiles; i++)
{ {
int this_file_error = 0; int this_file_error = 0;
...@@ -7372,6 +7515,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" ...@@ -7372,6 +7515,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
} }
else else
{ {
int value;
if (compare_debug) if (compare_debug)
{ {
free (debug_check_temp_file[0]); free (debug_check_temp_file[0]);
...@@ -7473,6 +7618,16 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" ...@@ -7473,6 +7618,16 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
if (lang_specific_pre_link ()) if (lang_specific_pre_link ())
errorcount++; errorcount++;
} }
}
/* If we have to run the linker, do it now. */
void
driver::maybe_run_linker (const char *argv0) const
{
size_t i;
int linker_was_run = 0;
int num_linker_inputs;
/* Determine if there are any linker input files. */ /* Determine if there are any linker input files. */
num_linker_inputs = 0; num_linker_inputs = 0;
...@@ -7524,7 +7679,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" ...@@ -7524,7 +7679,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
linker_plugin_file_spec = convert_white_space (temp_spec); linker_plugin_file_spec = convert_white_space (temp_spec);
} }
#endif #endif
lto_gcc_spec = argv[0]; lto_gcc_spec = argv0;
} }
/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
...@@ -7539,7 +7694,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" ...@@ -7539,7 +7694,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
" to the linker.\n\n")); " to the linker.\n\n"));
fflush (stdout); fflush (stdout);
} }
value = do_spec (link_command_spec); int value = do_spec (link_command_spec);
if (value < 0) if (value < 0)
errorcount = 1; errorcount = 1;
linker_was_run = (tmp != execution_count); linker_was_run = (tmp != execution_count);
...@@ -7554,7 +7709,13 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" ...@@ -7554,7 +7709,13 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
&& !(infiles[i].language && infiles[i].language[0] == '*')) && !(infiles[i].language && infiles[i].language[0] == '*'))
warning (0, "%s: linker input file unused because linking not done", warning (0, "%s: linker input file unused because linking not done",
outfiles[i]); outfiles[i]);
}
/* The end of "main". */
void
driver::final_actions () const
{
/* Delete some or all of the temporary files we made. */ /* Delete some or all of the temporary files we made. */
if (seen_error ()) if (seen_error ())
...@@ -7566,8 +7727,13 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" ...@@ -7566,8 +7727,13 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
printf (("\nFor bug reporting instructions, please see:\n")); printf (("\nFor bug reporting instructions, please see:\n"));
printf ("%s\n", bug_report_url); printf ("%s\n", bug_report_url);
} }
}
out: /* Determine what the exit code of the driver should be. */
int
driver::get_exit_code () const
{
return (signal_count != 0 ? 2 return (signal_count != 0 ? 2
: seen_error () ? (pass_exit_codes ? greatest_status : 1) : seen_error () ? (pass_exit_codes ? greatest_status : 1)
: 0); : 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment