void run_phase (phases_t phase, char *name, string_list_t *args) { char **argv; int argc = 1; string_item_t *p; char *output = NULL; char *input = NULL; boolean save_stderr = FALSE; int fdin, fdout; int forkpid; int waitpid; int waitstatus; int termsig; int num_maps; char *rld_path, *absoft_path; struct stat stat_buf; const boolean uses_message_system = (phase == P_f90_fe || phase == P_f90_cpp || phase == P_cppf90_fe); #if defined(__APPLE__) // pass -Wa,-W to assembler so we ignore unknowns int hack_as_W = 0; if (strcmp(name, "/usr/bin/gcc") == 0) { hack_as_W = 1; argc++; } #endif if (show_flag) { /* echo the command */ fprintf(stderr, "%s ", name); print_string_list(stderr, args); } if (!execute_flag) return; if (time_flag) init_time(); /* copy arg_list to argv format that exec wants */ for (p = args->head; p != NULL; p=p->next) { //bug# 581, bug #932, bug #1049 if (p->name == NULL) continue; argc++; } argv = (char **) malloc((argc+1)*sizeof(char*)); argv[0] = name; for (argc = 1, p = args->head; p != NULL; argc++, p=p->next) { //bug# 581, bug #932 if (p->name[0] == '\0') { argc--; continue; } /* don't put redirection in arg list */ if (strcmp(p->name, "<") == 0) { /* has input file */ input = p->next->name; break; } else if (strcmp(p->name, ">") == 0) { /* has output file */ output = p->next->name; break; } else if (strcmp(p->name, ">&") == 0) { /* has error output file */ output = p->next->name; save_stderr = TRUE; break; } argv[argc] = p->name; } #if defined(__APPLE__) if (hack_as_W) { #ifndef Is_True_On argv[argc++] = ""; // "-Wa,-W"; #endif } #endif argv[argc] = NULL; /* fork a process */ forkpid = fork(); if (forkpid == -1) { error("no more processes"); cleanup (); do_exit (RC_SYSTEM_ERROR); /* NOTREACHED */ } if (forkpid == 0) { char *my_path, *l_path, *l32_path, *nls_path, *env_path; /* child */ /* if we want memory stats, we have to wait for parent to connect to our /proc */ if (input != NULL) { if ((fdin = open (input, O_RDONLY)) == -1) { error ("cannot open input file %s", input); cleanup (); do_exit (RC_SYSTEM_ERROR); /* NOTREACHED */ } dup2 (fdin, fileno(stdin)); } if (output != NULL) { if ((fdout = creat (output, 0666)) == -1) { error ("cannot create output file %s", output); cleanup (); do_exit (RC_SYSTEM_ERROR); /* NOTREACHED */ } if (save_stderr) { dup2 (fdout, fileno(stderr)); } else { dup2 (fdout, fileno(stdout)); } } my_path = get_binutils_lib_path(); rld_path = get_phase_ld_library_path (phase); absoft_path = get_absoft_ld_library_path (phase); if (absoft_path != 0) asprintf(&my_path, "%s:%s", my_path, absoft_path); if (rld_path != 0) asprintf(&my_path, "%s:%s", my_path, rld_path); l_path = l32_path = my_path; if (ld_library_path) asprintf(&l_path, "%s:%s", my_path, ld_library_path); if (ld_libraryn32_path) asprintf(&l32_path, "%s:%s", my_path, ld_libraryn32_path); my_putenv("LD_LIBRARY_PATH", l_path); my_putenv("LD_LIBRARYN32_PATH", l32_path); // Set up NLSPATH, for the Fortran front end. nls_path = getenv("NLSPATH"); env_path = get_phase_dir(P_f90_fe); if (nls_path) { my_putenv("NLSPATH", "%s:%s/%%N.cat", nls_path, env_path); } else { my_putenv("NLSPATH", "%s/%%N.cat", env_path); } if (uses_message_system && getenv("ORIG_CMD_NAME") == NULL) my_putenv("ORIG_CMD_NAME", "%s", program_name); if (phase == P_f90_fe) { char *root; char *modulepath; int len; char *new_env; char *env_name = "FORTRAN_SYSTEM_MODULES="; char *env_val = "/usr/lib/f90modules"; root = getenv("TOOLROOT"); if (root != NULL) { len = strlen(env_val) + strlen(root) +3 + strlen(env_val); new_env = alloca(len); sprintf(new_env,"%s/%s:%s",root,env_val,env_val); env_val = new_env; } modulepath = string_copy(getenv("FORTRAN_SYSTEM_MODULES")); if (modulepath != NULL) { /* Append env_val to FORTRAN_SYSTEM_MODULES */ if (modulepath[strlen(modulepath)-1] == ':') { /* Just append env_val */ len = strlen(modulepath) + strlen(env_val) + 1; new_env = alloca(len); sprintf(new_env,"%s%s",modulepath,env_val); } else { /* append :env_val */ len = strlen(modulepath) + strlen(env_val) + 2; new_env = alloca(len); sprintf(new_env,"%s:%s",modulepath,env_val); } env_val = new_env; } my_putenv ("FORTRAN_SYSTEM_MODULES", "%s", env_val); } /* need to setenv COMPILER_PATH for collect to find ld */ my_putenv ("COMPILER_PATH", "%s", get_phase_dir(P_collect)); /* Tell IPA where to find the driver. */ #if defined(ABSOFT_EXTENSIONS) my_putenv ("COMPILER_BIN", "%s/" PSC_NAME_PREFIX "f90", get_executable_dir()); #else my_putenv ("COMPILER_BIN", "%s/" PSC_NAME_PREFIX "cc-" PSC_FULL_VERSION, get_executable_dir()); #endif my_execv(name, argv); } else { /* parent */ int procid; /* id of the /proc file */ while ((waitpid = wait (&waitstatus)) != forkpid) { if (waitpid == -1) { error("bad return from wait"); cleanup(); do_exit(RC_SYSTEM_ERROR); /* NOTREACHED */ } } if (time_flag) print_time(name); if (WIFSTOPPED(waitstatus)) { termsig = WSTOPSIG(waitstatus); error("STOPPED signal received from %s", name); cleanup(); do_exit(RC_SYSTEM_ERROR); /* NOTREACHED */ } else if (WIFEXITED(waitstatus)) { int status = WEXITSTATUS(waitstatus); extern int inline_t; boolean internal_err = FALSE; boolean user_err = FALSE; if (phase == P_prof) { /* Make sure the .cfb files were created before changing the STATUS to OKAY */ if (prof_file != NULL) { if (!(stat(fb_file, &stat_buf) != 0 && errno == ENOENT)) status = RC_OKAY; } else { internal_error("No count file was specified for a prof run"); perror(program_name); } } if (phase == P_f90_fe && keep_listing) { char *cif_file; cif_file = construct_given_name( drop_path(source_file), "T", TRUE); if (!(stat(cif_file, &stat_buf) != 0 && errno == ENOENT)) f90_fe_status = status; f90_fe_name = string_copy(name); /* Change the status to OKAY so that we can * execute the lister on the cif_file; we will * take appropriate action on this status once * the lister has finished executing. See below. */ status = RC_OKAY; } if (phase == P_lister) { if (status == RC_OKAY && f90_fe_status != RC_OKAY) { /* We had encountered an error in the F90_fe phase * but we ignored it so that we could execute the * lister on the cif file; we need to switch the * status to the status we received from F90_fe * and use the name of the F90_fe_phase, so that * we can issue a correct error message. */ status = f90_fe_status; name = string_copy(f90_fe_name); /* Reset f90_fe_status to OKAY for any further * compilations on other source files. */ f90_fe_status = RC_OKAY; } } switch (status) { case RC_OKAY: if (inline_t == UNDEFINED && is_matching_phase( get_phase_mask(phase), P_any_fe) ) { inline_t = FALSE; } break; case RC_NEED_INLINER: if (inline_t == UNDEFINED && is_matching_phase( get_phase_mask(phase), P_any_fe) ) { inline_t = TRUE; } /* completed successfully */ break; case RC_USER_ERROR: case RC_NORECOVER_USER_ERROR: case RC_SYSTEM_ERROR: case RC_GCC_ERROR: user_err = TRUE; break; case RC_OVERFLOW_ERROR: if (!ran_twice && phase == P_be) { /* try recompiling with larger limits */ ran_twice = TRUE; add_string (args, "-TENV:long_eh_offsets"); add_string (args, "-TENV:large_stack"); run_phase (phase, name, args); return; } internal_err = TRUE; break; case RC_INTERNAL_ERROR: internal_err = TRUE; break; default: internal_err = TRUE; break; } if (internal_err) { if (phase == P_ld || phase == P_ldplus || #ifdef KEY phase == P_gas || // bug 4846 #endif phase == P_gcpp || phase == P_gcpp_plus) { if (phase == P_gas) internal_error_occurred = 1; log_error("%s returned non-zero status %d", name, status); nomsg_error(status); } else { internal_error("%s returned non-zero status %d", name, status); } } else if (user_err) { /* assume phase will print diagnostics */ if (phase == P_c_gfe || phase == P_cplus_gfe) { nomsg_error(RC_INTERNAL_ERROR); } else if (!show_flag || save_stderr) { nomsg_error(RC_USER_ERROR); } else { error("%s returned non-zero status %d", name, status); } } ran_twice = FALSE; return; } else if(WIFSIGNALED(waitstatus)){ termsig = WTERMSIG(waitstatus); switch (termsig) { case SIGHUP: case SIGINT: case SIGQUIT: case SIGKILL: case SIGTERM: error("%s died due to signal %d", name, termsig); break; default: internal_error("%s died due to signal %d", name, termsig); break; } #ifndef __CYGWIN__ if(waitstatus & WCOREFLAG) { error("core dumped"); } #endif if (termsig == SIGKILL) { error("Probably caused by running out of swap space -- check %s", LOGFILE); } cleanup(); do_exit(RC_SYSTEM_ERROR); } else { /* cannot happen, I think! */ internal_error("driver exec'ing is confused"); return; } } }
void run_phase (phases_t phase, char *name, string_list_t *args) { const char **argv; int argc; string_item_t *p; char *output = NULL; char *input = NULL; boolean save_stderr = FALSE; int fdin, fdout; int waitstatus; int termsig; int num_maps; char *rld_path; struct stat stat_buf; const char* errmsg; int errnum; char *my_path; char *l_path; char *l32_path; char *nls_path; char *env_path; char *root_prefix; #if defined(BUILD_OS_DARWIN) int suppress_compiler_path = (phase == P_gas); #endif /* defined(BUILD_OS_DARWIN) */ const boolean uses_message_system = (phase == P_f90_fe || phase == P_cppf90_fe); if ((phase == P_be || phase == P_ipl) && add_heap_limit) { char str[200]; sprintf(str, "-OPT:hugepage_heap_limit=%d -OPT:hugepage_attr=%d", heap_limit, hugepage_attr); add_string(args, str); } if (show_flag) { /* echo the command */ fprintf(stderr, "%s ", name); print_string_list(stderr, args); } if (!execute_flag) return; if (time_flag) init_time(); /* copy arg_list to argv format that exec wants */ for (argc = 1, p = args->head; p != NULL; p = p->next) { //bug# 581, bug #932, bug #1049 if (p->name == NULL || p->name[0] == '\0') { continue; } argc++; } argv = (const char **)malloc((argc + 1) * sizeof(char *)); if (argv == NULL) { error("not enough memory"); cleanup(); do_exit(RC_SYSTEM_ERROR); } argv[0] = name; for (argc = 1, p = args->head; p != NULL; p = p->next) { //bug# 581, bug #932 if (p->name == NULL || p->name[0] == '\0') { continue; } /* don't put redirection in arg list */ if (strcmp(p->name, "<") == 0) { /* has input file */ input = p->next->name; break; } else if (strcmp(p->name, ">") == 0) { /* has output file */ output = p->next->name; break; } else if (strcmp(p->name, ">&") == 0) { /* has error output file */ output = p->next->name; save_stderr = TRUE; break; } argv[argc++] = p->name; } argv[argc] = NULL; if (show_command_only(name, argv)) { return; } my_path = get_binutils_lib_path(); rld_path = get_phase_ld_library_path(phase); if (rld_path != NULL) { asprintf(&my_path, "%s:%s", my_path, rld_path); } l_path = l32_path = my_path; if (ld_library_path) { asprintf(&l_path, "%s:%s", my_path, ld_library_path); } /* if we want memory stats, we have to wait for parent to connect to our /proc */ if (input != NULL) { if ((fdin = open (input, O_RDONLY)) == -1) { error ("cannot open input file %s", input); cleanup (); do_exit (RC_SYSTEM_ERROR); /* NOTREACHED */ } dup2 (fdin, fileno(stdin)); } if (output != NULL) { if ((fdout = creat (output, 0666)) == -1) { error ("cannot create output file %s", output); cleanup (); do_exit (RC_SYSTEM_ERROR); /* NOTREACHED */ } if (save_stderr) { dup2 (fdout, fileno(stderr)); } else { dup2 (fdout, fileno(stdout)); } } my_path = get_binutils_lib_path(); rld_path = get_phase_ld_library_path (phase); if (rld_path != 0) { asprintf(&my_path, "%s:%s:%s/%s", my_path, rld_path, rld_path, current_target->abi_name); } l_path = l32_path = my_path; if (ld_library_path) asprintf(&l_path, "%s:%s", my_path, ld_library_path); if (ld_libraryn32_path) asprintf(&l32_path, "%s:%s", my_path, ld_libraryn32_path); #if defined(BUILD_OS_DARWIN) /* Darwin static linker uses LD_LIBRARY_PATH, but dynamic * linker uses DYLD_LIBRARY_PATH */ my_putenv("DYLD_LIBRARY_PATH", "%s", l_path); #else /* defined(BUILD_OS_DARWIN) */ my_putenv("LD_LIBRARY_PATH", "%s", l_path); my_putenv("LD_LIBRARYN32_PATH", "%s", l32_path); #endif /* defined(BUILD_OS_DARWIN) */ // Set up NLSPATH, for the Fortran front end. nls_path = getenv("NLSPATH"); root_prefix = directory_path(get_executable_dir()); if (nls_path) { my_putenv("NLSPATH", "%s:%s%s/%%N.cat", nls_path, root_prefix, LIBPATH); } else { my_putenv("NLSPATH", "%s%s/%%N.cat", root_prefix, LIBPATH); } if (uses_message_system && getenv("ORIG_CMD_NAME") == NULL) my_putenv("ORIG_CMD_NAME", "%s", program_name); if (phase == P_f90_fe) { char *root; char *modulepath; int len; char *new_env; char *env_name = "FORTRAN_SYSTEM_MODULES="; char *env_val = "/usr/lib/f90modules"; root = getenv("TOOLROOT"); if (root != NULL) { len = strlen(env_val) + strlen(root) +3 + strlen(env_val); new_env = alloca(len); sprintf(new_env,"%s/%s:%s",root,env_val,env_val); env_val = new_env; } modulepath = string_copy(getenv("FORTRAN_SYSTEM_MODULES")); if (modulepath != NULL) { /* Append env_val to FORTRAN_SYSTEM_MODULES */ if (modulepath[strlen(modulepath)-1] == ':') { /* Just append env_val */ len = strlen(modulepath) + strlen(env_val) + 1; new_env = alloca(len); sprintf(new_env,"%s%s",modulepath,env_val); } else { /* append :env_val */ len = strlen(modulepath) + strlen(env_val) + 2; new_env = alloca(len); sprintf(new_env,"%s:%s",modulepath,env_val); } env_val = new_env; } my_putenv ("FORTRAN_SYSTEM_MODULES", "%s", env_val); } /* need to setenv COMPILER_PATH for collect to find ld */ if ( #ifdef KEY // gcc will invoke the cc1 in the COMPILER_PATH directory, // which is not what we want when we invoke gcc for // preprocessing. Bug 10164. #if defined(BUILD_OS_DARWIN) /* Driver uses gcc to run assembler. If we set COMPILER_PATH, * gcc uses PSC version of cc1, which doesn't accept one of * the options (-mmacosx-version-min=10.5.1) which Apple's * gcc driver passes to Apple's cc1. Looks like the * "is_matching_phase" test might already be trying to fix * this, but it's not succeeding. */ !suppress_compiler_path && #endif !is_matching_phase(get_phase_mask(P_any_cpp), phase) && #endif 1) { my_putenv("COMPILER_PATH", "%s", get_phase_dir(P_collect)); } /* Tell IPA where to find the driver. */ my_putenv("COMPILER_BIN", "%s/" PSC_NAME_PREFIX "cc-" PSC_FULL_VERSION, get_executable_dir()); if (execute(name, argv, input, output, &errmsg, &waitstatus) == -1) { error("execute failed: %s", errmsg); cleanup(); do_exit(RC_SYSTEM_ERROR); } if (time_flag) print_time(name); if (WIFSTOPPED(waitstatus)) { error("STOPPED signal received from %s", name); cleanup(); do_exit(RC_SYSTEM_ERROR); /* NOTREACHED */ } else if (WIFEXITED(waitstatus)) { int status = WEXITSTATUS(waitstatus); extern int inline_t; boolean internal_err = FALSE; boolean user_err = FALSE; if (phase == P_prof) { /* Make sure the .cfb files were created before changing the STATUS to OKAY */ if (prof_file != NULL) { if (!(stat(fb_file, &stat_buf) != 0 && errno == ENOENT)) { status = RC_OKAY; } } else { internal_error("No count file was specified for a prof run"); perror(program_name); } } if (phase == P_f90_fe && keep_listing) { char *cif_file = construct_given_name(drop_path(source_file), "T", TRUE); if (!(stat(cif_file, &stat_buf) != 0 && errno == ENOENT)) { f90_fe_status = status; } f90_fe_name = string_copy(name); /* Change the status to OKAY so that we can * execute the lister on the cif_file; we will * take appropriate action on this status once * the lister has finished executing. See below. */ status = RC_OKAY; } if (phase == P_lister) { if (status == RC_OKAY && f90_fe_status != RC_OKAY) { /* We had encountered an error in the F90_fe phase * but we ignored it so that we could execute the * lister on the cif file; we need to switch the * status to the status we received from F90_fe * and use the name of the F90_fe_phase, so that * we can issue a correct error message. */ status = f90_fe_status; name = string_copy(f90_fe_name); /* Reset f90_fe_status to OKAY for any further * compilations on other source files. */ f90_fe_status = RC_OKAY; } } switch (status) { case RC_OKAY: #ifdef KEY // If the command line has explicit inline // setting, follow it; else follow the // front-end request. Bug 11325. if (inline_t != UNDEFINED) { run_inline = inline_t; break; } #ifdef PATH64_ENABLE_GNU_FRONTEND // bug 10215 if (is_matching_phase(get_phase_mask(phase), P_wgen)) { run_inline = FALSE; } #endif // PATH64_ENABLE_GNU_FRONTEND #ifdef PATH64_ENABLE_PSCLANG // bug 10215 if (is_matching_phase(get_phase_mask(phase), P_psclang)) { run_inline = FALSE; } #endif // PATH64_ENABLE_PSCLANG break; #endif if (inline_t == UNDEFINED && is_matching_phase(get_phase_mask(phase), P_any_fe)) { #ifdef KEY run_inline = FALSE; // bug 11325 #else inline_t = FALSE; #endif } break; case RC_NEED_INLINER: #ifdef KEY // If the command line has explicit inline // setting, follow it; else follow the // front-end request. Bug 11325. if (inline_t != UNDEFINED) { run_inline = inline_t; break; } #ifdef PATH64_ENABLE_GNU_FRONTEND // bug 10215 if (is_matching_phase(get_phase_mask(phase), P_wgen)) { run_inline = TRUE; } #endif // PATH64_ENABLE_GNU_FRONTEND #ifdef PATH64_ENABLE_PSCLANG // bug 10215 if (is_matching_phase(get_phase_mask(phase), P_psclang)) { run_inline = TRUE; } #endif // PATH64_ENABLE_PSCLANG break; #endif if (inline_t == UNDEFINED && is_matching_phase(get_phase_mask(phase), P_any_fe)) { #ifdef KEY run_inline = TRUE; // bug 11325 #else inline_t = TRUE; #endif } /* completed successfully */ break; case RC_USER_ERROR: case RC_NORECOVER_USER_ERROR: case RC_SYSTEM_ERROR: case RC_GCC_ERROR: #ifdef KEY case RC_RTL_MISSING_ERROR: /* bug 14054 */ #endif user_err = TRUE; break; case RC_OVERFLOW_ERROR: if (!ran_twice && phase == P_be) { /* try recompiling with larger limits */ ran_twice = TRUE; add_string(args, "-TENV:long_eh_offsets"); add_string(args, "-TENV:large_stack"); run_phase(phase, name, args); return; } internal_err = TRUE; break; #ifdef KEY case RC_GCC_INTERNAL_ERROR: #endif case RC_INTERNAL_ERROR: internal_err = TRUE; break; default: internal_err = TRUE; break; } if (internal_err) { if (phase == P_ld || phase == P_ldplus || #ifdef KEY phase == P_gas || // bug 4846 phase == P_f_coco || // bug 9058 #ifdef PATH64_ENABLE_PSCLANG phase == P_psclang_cpp || phase == P_psclang || #endif // PATH64_ENABLE_PSCLANG status == RC_GCC_INTERNAL_ERROR || //bug 9637 #endif // KEY #ifdef PATH64_ENABLE_GNU_FRONTEND phase == P_spin_cc1 || phase == P_spin_cc1plus || phase == P_gcpp || phase == P_gcpp_plus || #endif // PATH64_ENABLE_GNU_FRONTEND TRUE) { if (phase == P_gas || status == RC_GCC_INTERNAL_ERROR) { internal_error_occurred = 1; } log_error("%s returned non-zero status %d", name, status); nomsg_error(status); } else { internal_error("%s returned non-zero status %d", name, status); } } else if (user_err) { /* assume phase will print diagnostics */ if (phase == P_c_gfe || phase == P_cplus_gfe #ifdef PATH64_ENABLE_GNU_FRONTEND #ifdef KEY || phase == P_wgen || phase == P_spin_cc1 || phase == P_spin_cc1plus #endif // KEY #endif // PATH64_ENABLE_GNU_FRONTEND ) { nomsg_error(RC_INTERNAL_ERROR); } else if (!show_flag || save_stderr) { nomsg_error(RC_USER_ERROR); } else { error("%s returned non-zero status %d", name, status); } } ran_twice = FALSE; return; } else if(WIFSIGNALED(waitstatus)) { termsig = WTERMSIG(waitstatus); switch (termsig) { #ifdef SIGHUP case SIGHUP: #endif case SIGINT: #ifdef SIGQUIT case SIGQUIT: #endif #ifdef SIGKILL case SIGKILL: #endif case SIGTERM: error("%s died due to signal %d", name, termsig); break; default: internal_error("%s died due to signal %d", name, termsig); break; } if(waitstatus & WCOREFLAG) { error("core dumped"); } #ifdef SIGKILL if (termsig == SIGKILL) { error("Probably caused by running out of swap space -- check %s", LOGFILE); } #endif cleanup(); do_exit(RC_SYSTEM_ERROR); } else { /* cannot happen, I think! */ internal_error("driver exec'ing is confused"); return; } }