diff options
Diffstat (limited to 'gcc/c/gupcspec.c')
-rw-r--r-- | gcc/c/gupcspec.c | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/gcc/c/gupcspec.c b/gcc/c/gupcspec.c new file mode 100644 index 00000000000..e11ebe163f7 --- /dev/null +++ b/gcc/c/gupcspec.c @@ -0,0 +1,307 @@ +/* gupcspec.c: the UPC compiler driver program + Copyright (C) 2001-2016 Free Software Foundation, Inc. + Contributed by Gary Funck <gary@intrepid.com> + and Nenad Vukicevic <nenad@intrepid.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "gcc.h" +#include "opts.h" + +#include "tm.h" + + +/* GUPC driver - derived from fortran/gfortranspec.c. */ + +/* The original argument list and related info is copied here. */ +static unsigned int gupc_xargc; +static const struct cl_decoded_option *gupc_x_decoded_options; +static void append_arg (const struct cl_decoded_option *); + +/* The new argument list will be built here. */ +static unsigned int gupc_newargc; +static struct cl_decoded_option *gupc_new_decoded_options; + +static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX; +static const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX; + +/* By default the linker is always invoked. */ +static int invoke_linker = 1; + +static int match_suffix (const char *s, const char *suffix); + +#define END_ARGS ((char *) 0) + +/* Return true if the strings S1 and S2 are either both NULL + * or both the same string. */ + +static bool +strings_same (const char *s1, const char *s2) +{ + return s1 == s2 || (s1 != NULL && s2 != NULL && strcmp (s1, s2) == 0); +} + +/* Return whether decoded option structures OPT1 and OPT2 are the + same. */ + +static bool +options_same (const struct cl_decoded_option *opt1, + const struct cl_decoded_option *opt2) +{ + return (opt1->opt_index == opt2->opt_index + && strings_same (opt1->arg, opt2->arg) + && strings_same (opt1->orig_option_with_args_text, + opt2->orig_option_with_args_text) + && strings_same (opt1->canonical_option[0], + opt2->canonical_option[0]) + && strings_same (opt1->canonical_option[1], + opt2->canonical_option[1]) + && strings_same (opt1->canonical_option[2], + opt2->canonical_option[2]) + && strings_same (opt1->canonical_option[3], + opt2->canonical_option[3]) + && (opt1->canonical_option_num_elements + == opt2->canonical_option_num_elements) + && opt1->value == opt2->value && opt1->errors == opt2->errors); +} + +/* Append another argument to the list being built. As long as it is + identical to the corresponding arg in the original list, just increment + the new arg count. Otherwise allocate a new list, etc. */ + +static void +append_arg (const struct cl_decoded_option *arg) +{ + static unsigned int newargsize; + + if (gupc_new_decoded_options == gupc_x_decoded_options + && gupc_newargc < gupc_xargc + && options_same (arg, &gupc_x_decoded_options[gupc_newargc])) + { + ++gupc_newargc; + return; /* Nothing new here. */ + } + + if (gupc_new_decoded_options == gupc_x_decoded_options) + { /* Make new arglist. */ + unsigned int i; + + newargsize = (gupc_xargc << 2) + 20; /* This should handle all. */ + gupc_new_decoded_options = + XNEWVEC (struct cl_decoded_option, newargsize); + + /* Copy what has been done so far. */ + for (i = 0; i < gupc_newargc; ++i) + gupc_new_decoded_options[i] = gupc_x_decoded_options[i]; + } + + if (gupc_newargc == newargsize) + fatal_error (input_location, "overflowed output arg list for %qs", + arg->orig_option_with_args_text); + + gupc_new_decoded_options[gupc_newargc++] = *arg; +} + +/* Append an option described by OPT_INDEX, ARG and VALUE to the list + being built. */ +static void +append_option (size_t opt_index, const char *arg, int value) +{ + struct cl_decoded_option decoded; + + generate_option (opt_index, arg, value, CL_DRIVER, &decoded); + append_arg (&decoded); +} + +/* Return TRUE if SUFFIX is found at the end of the string S. */ + +static int +match_suffix (const char *s, const char *suffix) +{ + int slen = strlen (s); + int xlen = strlen (suffix); + const char *start = (xlen <= slen) ? s + slen - xlen : 0; + return start && !strncmp (start, suffix, xlen); +} + +/* The UPC-specific aspects of the 'gupc' compiler driver. */ + +void +lang_specific_driver (struct cl_decoded_option **in_decoded_options, + unsigned int *in_decoded_options_count, + int *in_added_libraries ATTRIBUTE_UNUSED) +{ + struct cl_decoded_option *decoded_options = *in_decoded_options; + unsigned int i; + int is_x_in_effect = 0; + int is_x_upc_in_effect = 0; + int verbose = 0; + int n_infiles = 0; + int n_outfiles = 0; + int pre_processed = 0; + + gupc_xargc = *in_decoded_options_count; + gupc_x_decoded_options = decoded_options; + gupc_newargc = 0; + gupc_new_decoded_options = decoded_options; + + /* First pass through the argument list. */ + + /* Check to see if any switches are asserted that inhibit linking + and record the presence of other switches that may require + special handling. */ + for (i = 1; i < gupc_xargc; ++i) + { + if (decoded_options[i].errors & CL_ERR_MISSING_ARG) + continue; + + switch (decoded_options[i].opt_index) + { + + case OPT_SPECIAL_input_file: + ++n_infiles; + continue; + + case OPT_nostdlib: + case OPT_nodefaultlibs: + case OPT_c: + case OPT_S: + case OPT_fsyntax_only: + case OPT_E: + /* These options disable linking entirely or linking of the + standard libraries. */ + invoke_linker = 0; + break; + + case OPT_fpreprocessed: + pre_processed = 1; + break; + + case OPT_l: + ++n_infiles; + break; + + case OPT_o: + ++n_outfiles; + break; + + case OPT_v: + verbose = 1; + break; + + case OPT__version: + /* Optional GUPC version string. Let GCC handle it for now. */ + break; + + case OPT__help: + /* Let gcc.c handle this, as it has a really + cool facility for handling --help and --verbose --help. */ + return; + + default: + break; + } + } + + /* Create the new argument list. */ + + /* Start with the compiler itself. */ + append_arg (&decoded_options[0]); + + /* Always assert -fupc. */ + append_option (OPT_fupc, NULL, 1); + + /* If there are no input files, no need for the library. */ + if (n_infiles == 0) + invoke_linker = 0; + + /* Copy in the arguments as passed to 'upc' */ + is_x_in_effect = 0; + is_x_upc_in_effect = 0; + for (i = 1; i < gupc_xargc; ++i) + { + /* Skip -fupc, we asserted it above. */ + if (decoded_options[i].opt_index == OPT_fupc) + continue; + + /* Check for "-x [c,upc,..]". */ + if (decoded_options[i].opt_index == OPT_x) + { + /* Go to default if "none" found. */ + if (!strcmp (decoded_options[i].arg, "none")) + { + is_x_in_effect = 0; + is_x_upc_in_effect = 0; + } + else + is_x_in_effect = 1; + } + + /* By default, driver accepts C files as UPC files. Unless there + is "-x" option in affect. */ + if (decoded_options[i].opt_index == OPT_SPECIAL_input_file) + { + const int is_c_file = match_suffix (decoded_options[i].arg, ".c") + || match_suffix (decoded_options[i].arg, ".h") + || (pre_processed && match_suffix (decoded_options[i].arg, ".i")); + if (is_c_file) + { + if ( !(is_x_in_effect || is_x_upc_in_effect)) + { + append_option (OPT_x, "upc", 1); + is_x_upc_in_effect = 1; + } + append_arg (&decoded_options[i]); + continue; + } + else + { + if (is_x_upc_in_effect) + { + is_x_upc_in_effect = 0; + append_option (OPT_x, "none", 1); + } + } + } + append_arg (&decoded_options[i]); + } + + if (verbose) + { + fprintf (stderr, "Driving:"); + for (i = 0; i < gupc_newargc; i++) + fprintf (stderr, " %s", + gupc_new_decoded_options[i].orig_option_with_args_text); + fprintf (stderr, "\n"); + } + + *in_decoded_options_count = gupc_newargc; + *in_decoded_options = gupc_new_decoded_options; +} + +/* Called before linking. Returns 0 on success and -1 on failure. */ +int +lang_specific_pre_link (void) +{ + return 0; +} + +/* Number of extra output files that lang_specific_pre_link may generate. */ +int lang_specific_extra_outfiles = 0; /* Not used for GUPC. */ |