/* Main entry point. This is gcc driver driver! Interpret -arch flag from the list of input arguments. Invoke appropriate compiler driver. 'lipo' the results if more than one -arch is supplied. */ int main (int argc, const char **argv) { size_t i; int l, pid, argv_0_len, prog_len; char *errmsg_fmt, *errmsg_arg; char *override_option_str = NULL; char path_buffer[2*PATH_MAX+1]; int linklen; total_argc = argc; prog_len = 0; argv_0_len = strlen (argv[0]); /* Get the progname, required by pexecute () and program location. */ prog_len = get_prog_name_len (argv[0]); /* If argv[0] is all program name (no slashes), search the PATH environment variable to get the fully resolved path to the executable. */ if (prog_len == argv_0_len) { #ifdef DEBUG progname = argv[0] + argv_0_len - prog_len; fprintf (stderr,"%s: before PATH resolution, full progname = %s\n", argv[0]+argv_0_len-prog_len, argv[0]); #endif argv[0] = resolve_path_to_executable (argv[0]); prog_len = get_prog_name_len (argv[0]); argv_0_len = strlen(argv[0]); } /* If argv[0] is a symbolic link, use the directory of the pointed-to file to find compiler components. */ if ((linklen = readlink (argv[0], path_buffer, PATH_MAX)) != -1) { /* readlink succeeds if argv[0] is a symlink. path_buffer now contains the file referenced. */ path_buffer[linklen] = '\0'; #ifdef DEBUG progname = argv[0] + argv_0_len - prog_len; fprintf (stderr, "%s: before symlink, full prog = %s target = %s\n", progname, argv[0], path_buffer); #endif argv[0] = resolve_symlink(argv[0], path_buffer, argv_0_len, prog_len); argv_0_len = strlen(argv[0]); /* Get the progname, required by pexecute () and program location. */ prog_len = get_prog_name_len (argv[0]); #ifdef DEBUG progname = argv[0] + argv_0_len - prog_len; printf("%s: ARGV[0] after symlink = %s\n", progname, argv[0]); #endif } progname = argv[0] + argv_0_len - prog_len; /* Setup driver prefix. */ prefix_len = argv_0_len - prog_len; curr_dir = (char *) malloc (sizeof (char) * (prefix_len + 1)); strncpy (curr_dir, argv[0], prefix_len); curr_dir[prefix_len] = '\0'; driver_exec_prefix = (argv[0], "/usr/bin", curr_dir); #ifdef DEBUG fprintf (stderr,"%s: full progname = %s\n", progname, argv[0]); fprintf (stderr,"%s: progname = %s\n", progname, progname); fprintf (stderr,"%s: driver_exec_prefix = %s\n", progname, driver_exec_prefix); #endif /* Before we get too far, rewrite the command line with any requested overrides */ if ((override_option_str = getenv ("QA_OVERRIDE_GCC3_OPTIONS")) != NULL) rewrite_command_line(override_option_str, &argc, (char***)&argv); initialize (); /* Process arguments. Take appropriate actions when -arch, -c, -S, -E, -o is encountered. Find input file name. */ for (i = 1; i < argc; i++) { if (!strcmp (argv[i], "-arch")) { if (i + 1 >= argc) abort (); add_arch (argv[i+1]); i++; } else if (!strcmp (argv[i], "-c")) { new_argv[new_argc++] = argv[i]; compile_only_request = 1; } else if (!strcmp (argv[i], "-S")) { new_argv[new_argc++] = argv[i]; asm_output_request = 1; } else if (!strcmp (argv[i], "-E")) { new_argv[new_argc++] = argv[i]; preprocessed_output_request = 1; } else if (!strcmp (argv[i], "-MD") || !strcmp (argv[i], "-MMD")) { new_argv[new_argc++] = argv[i]; dash_capital_m_seen = 1; } else if (!strcmp (argv[i], "-m32")) { new_argv[new_argc++] = argv[i]; dash_m32_seen = 1; } else if (!strcmp (argv[i], "-m64")) { new_argv[new_argc++] = argv[i]; dash_m64_seen = 1; } else if (!strcmp (argv[i], "-dynamiclib")) { new_argv[new_argc++] = argv[i]; dash_dynamiclib_seen = 1; } else if (!strcmp (argv[i], "-v")) { new_argv[new_argc++] = argv[i]; verbose_flag = 1; } else if (!strcmp (argv[i], "-o")) { if (i + 1 >= argc) fatal ("argument to '-o' is missing"); output_filename = argv[i+1]; i++; } else if ((! strcmp (argv[i], "-pass-exit-codes")) || (! strcmp (argv[i], "-print-search-dirs")) || (! strcmp (argv[i], "-print-libgcc-file-name")) || (! strncmp (argv[i], "-print-file-name=", 17)) || (! strncmp (argv[i], "-print-prog-name=", 17)) || (! strcmp (argv[i], "-print-multi-lib")) || (! strcmp (argv[i], "-print-multi-directory")) || (! strcmp (argv[i], "-print-multi-os-directory")) || (! strcmp (argv[i], "-ftarget-help")) || (! strcmp (argv[i], "-fhelp")) || (! strcmp (argv[i], "+e")) || (! strncmp (argv[i], "-Wa,",4)) || (! strncmp (argv[i], "-Wp,",4)) || (! strncmp (argv[i], "-Wl,",4)) || (! strncmp (argv[i], "-l", 2)) || (! strncmp (argv[i], "-weak-l", 7)) || (! strncmp (argv[i], "-specs=", 7)) || (! strcmp (argv[i], "-ObjC")) || (! strcmp (argv[i], "-fobjC")) || (! strcmp (argv[i], "-ObjC++")) || (! strcmp (argv[i], "-time")) || (! strcmp (argv[i], "-###")) || (! strcmp (argv[i], "-fconstant-cfstrings")) || (! strcmp (argv[i], "-fno-constant-cfstrings")) || (! strcmp (argv[i], "-static-libgcc")) || (! strcmp (argv[i], "-shared-libgcc")) || (! strcmp (argv[i], "-pipe")) ) { new_argv[new_argc++] = argv[i]; } else if (! strcmp (argv[i], "-save-temps") || ! strcmp (argv[i], "--save-temps")) { new_argv[new_argc++] = argv[i]; save_temps_seen = 1; } else if ((! strcmp (argv[i], "-Xlinker")) || (! strcmp (argv[i], "-Xassembler")) || (! strcmp (argv[i], "-Xpreprocessor")) || (! strcmp (argv[i], "-l")) || (! strcmp (argv[i], "-weak_library")) || (! strcmp (argv[i], "-weak_framework")) || (! strcmp (argv[i], "-specs")) || (! strcmp (argv[i], "-framework")) ) { new_argv[new_argc++] = argv[i]; i++; new_argv[new_argc++] = argv[i]; } else if (! strncmp (argv[i], "-Xarch_", 7)) { arch_conditional[new_argc] = get_arch_name (argv[i] + 7); i++; new_argv[new_argc++] = argv[i]; } else if (argv[i][0] == '-' && argv[i][1] != 0) { const char *p = &argv[i][1]; int c = *p; /* First copy this flag itself. */ new_argv[new_argc++] = argv[i]; if (argv[i][1] == 'M') dash_capital_m_seen = 1; /* Now copy this flag's arguments, if any, appropriately. */ if ((SWITCH_TAKES_ARG (c) > (p[1] != 0)) || WORD_SWITCH_TAKES_ARG (p)) { int j = 0; int n_args = WORD_SWITCH_TAKES_ARG (p); 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 >= argc) fatal ("argument to `-%s' is missing", p); while ( j < n_args) { i++; new_argv[new_argc++] = argv[i]; j++; } } } else { struct input_filename *ifn; new_argv[new_argc++] = argv[i]; ifn = (struct input_filename *) malloc (sizeof (struct input_filename)); ifn->name = argv[i]; ifn->index = i; ifn->next = NULL; num_infiles++; if (last_infile) last_infile->next = ifn; else in_files = ifn; last_infile = ifn; } } #if 0 if (num_infiles == 0) fatal ("no input files"); #endif if (num_arches == 0) add_arch(get_arch_name(NULL)); if (num_arches > 1) { if (preprocessed_output_request || save_temps_seen || asm_output_request || dash_capital_m_seen) fatal ("-E, -S, -save-temps and -M options are not allowed with multiple -arch flags"); } /* If -arch is not present OR Only one -arch <blah> is specified. Invoke appropriate compiler driver. FAT build is not required in this case. */ if (num_arches == 1) { int arch_specific_argc; const char **arch_specific_argv; /* Find compiler driver based on -arch <foo> and add approriate -m* argument. */ new_argv[0] = get_driver_name (get_arch_name (arches[0])); new_argc = new_argc + add_arch_options (0, new_argv, new_argc); #ifdef DEBUG printf ("%s: invoking single driver name = %s\n", progname, new_argv[0]); #endif /* Re insert output file name. */ if (output_filename) { new_argv[new_argc++] = "-o"; new_argv[new_argc++] = output_filename; } /* Add the NULL. */ new_argv[new_argc] = NULL; arch_specific_argv = (const char **) malloc ((new_argc + 1) * sizeof (const char *)); arch_specific_argc = filter_args_for_arch (new_argv, new_argc, arch_specific_argv, get_arch_name (arches[0])); #ifdef DEBUG debug_command_line (arch_specific_argv, arch_specific_argc); #endif pid = pexecute (arch_specific_argv[0], (char *const *)arch_specific_argv, progname, NULL, &errmsg_fmt, &errmsg_arg, PEXECUTE_SEARCH | PEXECUTE_ONE); if (pid == -1) pfatal_pexecute (errmsg_fmt, errmsg_arg); do_wait (pid, arch_specific_argv[0]); } else { /* Handle multiple -arch <blah>. */ /* If more than one input files are supplied but only one output filename is present then IMA will be used. */ if (num_infiles > 1 && !compile_only_request) ima_is_used = 1; /* Linker wants to know this in case of multiple -arch. */ if (!compile_only_request && !dash_dynamiclib_seen) new_argv[new_argc++] = "-Wl,-arch_multiple"; /* If only one input file is specified OR IMA is used then expected output is one FAT binary. */ if (num_infiles == 1 || ima_is_used) { const char *out_file; /* Create output file name based on input filename, if required. */ if (compile_only_request && !output_filename && num_infiles == 1) out_file = strip_path_and_suffix (in_files->name, ".o"); else out_file = (output_filename ? output_filename : final_output); /* Linker wants to know name of output file using one extra arg. */ if (!compile_only_request) { char *oname = (char *)(output_filename ? output_filename : final_output); char *n = malloc (sizeof (char) * (strlen (oname) + 5)); strcpy (n, "-Wl,"); strcat (n, oname); new_argv[new_argc++] = "-Wl,-final_output"; new_argv[new_argc++] = n; } /* Compile file(s) for each arch and lipo 'em together. */ do_compile (new_argv, new_argc); /* Make FAT binary by combining individual output files for each architecture, using 'lipo'. */ do_lipo (0, out_file); } else { /* Multiple input files are present and IMA is not used. Which means need to generate multiple FAT files. */ do_compile_separately (); do_lipo_separately (); } } final_cleanup (); free (curr_dir); return greatest_status; }
static void lookup_option (Option *xopt, int *xskip, const char **xarg, const char *text) { Option opt = OPTION_; int skip; const char *arg = NULL; if ((skip = SWITCH_TAKES_ARG (text[1]))) skip -= (text[2] != '\0'); /* See gcc.c. */ if (text[1] == 'B') opt = OPTION_B, skip = (text[2] == '\0'), arg = text + 2; else if (text[1] == 'b') opt = OPTION_b, skip = (text[2] == '\0'), arg = text + 2; else if ((text[1] == 'c') && (text[2] == '\0')) opt = OPTION_c, skip = 0; else if ((text[1] == 'E') && (text[2] == '\0')) opt = OPTION_E, skip = 0; else if (text[1] == 'i') opt = OPTION_i, skip = 0; else if (text[1] == 'l') opt = OPTION_l; else if (text[1] == 'L') opt = OPTION_L, arg = text + 2; else if (text[1] == 'o') opt = OPTION_o; else if ((text[1] == 'S') && (text[2] == '\0')) opt = OPTION_S, skip = 0; else if (text[1] == 'V') opt = OPTION_V, skip = (text[2] == '\0'); else if ((text[1] == 'v') && (text[2] == '\0')) opt = OPTION_v, skip = 0; else if (text[1] == 'x') opt = OPTION_x, arg = text + 2; else if (text[1] == 'J') ; else { if ((skip = WORD_SWITCH_TAKES_ARG (text + 1)) != 0) /* See gcc.c. */ ; else if (!strcmp (text, "-fhelp")) /* Really --help!! */ opt = OPTION_help; else if (!strcmp (text, "-nostdlib") || !strcmp (text, "-nodefaultlibs")) opt = OPTION_nostdlib; else if (!strcmp (text, "-fsyntax-only")) opt = OPTION_syntax_only; else if (!strcmp (text, "-static-libgfortran")) opt = OPTION_static_libgfortran; else if (!strcmp (text, "-fversion")) /* Really --version!! */ opt = OPTION_version; else if (!strcmp (text, "-Xlinker") || !strcmp (text, "-specs")) skip = 1; else skip = 0; } if (xopt != NULL) *xopt = opt; if (xskip != NULL) *xskip = skip; if (xarg != NULL) { if ((arg != NULL) && (arg[0] == '\0')) *xarg = NULL; else *xarg = arg; } }
static void __upc_process_switches (char *pgm, int *argc, char *argv[]) { long int threads_switch_value = 0; #ifdef GUPCR_USE_PTHREADS long int pthreads_switch_value = 0; #endif /* GUPCR_USE_PTHREADS */ long int heap_switch_value = 0; const char *gum_debug_env = getenv (GUM_DEBUG_ENV); /* Check if GUM debugging is enabled by environment variable. */ if (gum_debug_env && atoi(gum_debug_env)) { __upc_gum_debug = 1; } while (*argc >= 2) { const char *arg = argv[1]; const char *tval; if (!strcmp (arg, "--")) { /* -- terminates any upc switches */ __upc_shift_args (argc, argv); break; /* exit loop */ } if (SWITCH_TAKES_ARG (arg) && (*argc < 3)) { fprintf (stderr, "%s argument requires a value\n", arg); __upc_print_help_and_exit (pgm); } if (!strncmp (arg, "-fupc-threads-", 14)) { tval = arg + 14; if (!__upc_get_int_value (tval, &threads_switch_value, 0, 1L, (long int) GUPCR_THREADS_MAX)) { fprintf (stderr, "Invalid THREADS value\n"); __upc_print_help_and_exit (pgm); } } else if (!strcmp (arg, "-n")) { tval = argv[2]; if (!__upc_get_int_value (tval, &threads_switch_value, 0, 1L, (long int) GUPCR_THREADS_MAX)) { fprintf (stderr, "Invalid THREADS value\n"); __upc_print_help_and_exit (pgm); } __upc_shift_args (argc, argv); } else if (!strncmp (arg, "-n", 2)) { tval = arg + 2; if (!__upc_get_int_value (tval, &threads_switch_value, 0, 1L, (long int) GUPCR_THREADS_MAX)) { fprintf (stderr, "Invalid THREADS value\n"); __upc_print_help_and_exit (pgm); } } #ifdef GUPCR_USE_PTHREADS else if (!strncmp (arg, "-fupc-pthreads-", 15)) { tval = arg + 15; if (!__upc_get_int_value (tval, &pthreads_switch_value, 0, 1L, (long int) GUPCR_THREADS_MAX)) { fprintf (stderr, "Invalid UPC pthreads value\n"); __upc_print_help_and_exit (pgm); } } #endif /* GUPCR_USE_PTHREADS */ else if (!strncmp (arg, "-fupc-heap-", 11)) { tval = arg + 11; if (!__upc_get_int_value (tval, &heap_switch_value, 1, 1L, GUPCR_MAX_HEAP_SIZE)) { fprintf (stderr, "Invalid heap size value\n"); __upc_print_help_and_exit (pgm); } } else if (!strcmp (arg, "-heap")) { tval = argv[2]; if (!__upc_get_int_value (tval, &heap_switch_value, 1, 1L, GUPCR_MAX_HEAP_SIZE)) { fprintf (stderr, "Invalid heap size value\n"); __upc_print_help_and_exit (pgm); } __upc_shift_args (argc, argv); } else if (!strncmp (arg, "-heap", 5)) { tval = arg + 5; if (!__upc_get_int_value (tval, &heap_switch_value, 1, 1L, GUPCR_MAX_HEAP_SIZE)) { fprintf (stderr, "Invalid heap size value\n"); __upc_print_help_and_exit (pgm); } __upc_shift_args (argc, argv); } else if (!strcmp (arg, "-sched-policy")) { if (!__upc_affinity_supported ()) { fprintf (stderr, "Scheduling affinity not supported or configured\n"); __upc_print_help_and_exit (pgm); } tval = argv[2]; if (!strcmp (tval, "node")) { if (!__upc_numa_supported ()) { fprintf (stderr, "NUMA node affinity not supported or configured\n"); __upc_print_help_and_exit (pgm); } __upc_sched_policy = GUPCR_SCHED_POLICY_NODE; } else if (!strcmp (tval, "strict")) { __upc_sched_policy = GUPCR_SCHED_POLICY_CPU_STRICT; } else if (!strcmp (tval, "cpu")) { __upc_sched_policy = GUPCR_SCHED_POLICY_CPU; } else if (!strcmp (tval, "auto")) { __upc_sched_policy = GUPCR_SCHED_POLICY_AUTO; } else { fprintf (stderr, "Invalid scheduling policy specified\n"); __upc_print_help_and_exit (pgm); } __upc_shift_args (argc, argv); } else if (!strcmp (arg, "-mem-policy")) { if (!__upc_numa_supported ()) { fprintf (stderr, "NUMA node affinity not supported or configured\n"); __upc_print_help_and_exit (pgm); } tval = argv[2]; if (!strcmp (tval, "node")) { __upc_mem_policy = GUPCR_MEM_POLICY_NODE; } else if (!strcmp (tval, "strict")) { __upc_mem_policy = GUPCR_MEM_POLICY_STRICT; } else if (!strcmp (tval, "auto")) { __upc_mem_policy = GUPCR_MEM_POLICY_AUTO; } else { fprintf (stderr, "Invalid memory allocation policy specified\n"); __upc_print_help_and_exit (pgm); } __upc_shift_args (argc, argv); } else if (!strcmp (arg, "-sched-cpu-avoid")) { if (!__upc_affinity_supported ()) { fprintf (stderr, "Scheduling affinity not supported or configured\n"); __upc_print_help_and_exit (pgm); } tval = argv[2]; if (!__upc_get_cpu_avoid_values (tval, __upc_cpu_avoid_set)) { fprintf (stderr, "Invalid CPU to avoid string\n"); __upc_print_help_and_exit (pgm); } __upc_shift_args (argc, argv); } else if (!strcmp (arg, "-g")) { __upc_gum_debug = 1; } else /* exit loop at first unrecognized switch. */ break; __upc_shift_args (argc, argv); } if (heap_switch_value) { __upc_init_heap_size = heap_switch_value; } if (threads_switch_value) { if (THREADS > 0) { if (threads_switch_value != THREADS) { fprintf (stderr, "%s: UPC error: The value of the" " -fupc-threads-N switch: %ld," " does not agree with the value given at" " compile-time: %d\n", pgm, threads_switch_value, THREADS); exit (2); } } else { THREADS = threads_switch_value; #ifdef GUPCR_USE_PTHREADS if (UPC_PTHREADS == -1) { /* UPC threads per process specified as 'dynamic'. Set it GUPCR_THREADS to specified value of THREADS. */ UPC_PTHREADS = THREADS; } #endif /* GUPCR_USE_PTHREADS */ } } if (THREADS <= 0) { fprintf (stderr, "%s: UPC error: No value given for THREADS\n", pgm); __upc_print_help_and_exit (pgm); } #ifdef GUPCR_USE_PTHREADS if (pthreads_switch_value) { if (pthreads_switch_value != THREADS) { fprintf (stderr, "%s: UPC error: pthreads value must equal the number of UPC threads\n", pgm); __upc_print_help_and_exit (pgm); } else { UPC_PTHREADS = pthreads_switch_value; } } #endif /* GUPCR_USE_PTHREADS */ #if !GUPCR_HAVE_GUM_DEBUG if (__upc_gum_debug) { fprintf (stderr, "UPC debugging not supported or configured\n"); __upc_print_help_and_exit (pgm); } #endif }