Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 /* ==================================================================== 00037 * ==================================================================== 00038 * 00039 * 00040 * Revision history: 00041 * 13-Feb-95 - Original Version 00042 * 00043 * Description: 00044 * Main driver for the entire backend. 00045 * 00046 * ==================================================================== 00047 * ==================================================================== 00048 */ 00049 00050 #include <sys/types.h> 00051 #include <elf.h> /* for wn.h */ 00052 #include <cmplrs/rcodes.h> 00053 #include <dirent.h> 00054 #include <iostream> 00055 #include <sys/param.h> 00056 00057 #include "defs.h" 00058 #include "dso.h" /* for load_so() */ 00059 #include "errors.h" /* Set_Error_Tables(), etc. */ 00060 #include "err_host.tab" /* load all the error messages */ 00061 #include "erglob.h" /* for EC_ errmsg */ 00062 #include "erauxdesc.h" /* for BE error messages */ 00063 #include "mempool.h" /* for MEM_Initialze() */ 00064 #include "phase.h" /* for PHASE_CG */ 00065 #include "be_util.h" /* for Reset_Current_PU_Count(), etc */ 00066 #include "wn.h" /* for WN */ 00067 #include "driver_util.h" /* for Process_Command_Line() */ 00068 #include "timing.h" /* for Reset_Timer(), etc. */ 00069 #include "glob.h" /* for Show_Progress */ 00070 #include "stab.h" /* for ir_bread.h */ 00071 #include "pu_info.h" /* for PU_Info */ 00072 #include "ir_bread.h" /* for Read_Global_Info() */ 00073 #include "ir_bwrite.h" /* for Write_Global_Info(), etc. */ 00074 #include "config.h" /* for LNO_Path, etc. */ 00075 #include "config_opt.h" /* for Instrumentation_Enabled */ 00076 #include "config_list.h" /* for List_Enabled, etc. */ 00077 #include "config_lno.h" /* for LNO_Run_Lego, etc. */ 00078 #include "file_util.h" /* for New_Extension () */ 00079 #include "xstats.h" /* for Print_Stats () */ 00080 #include "data_layout.h" /* for Initialize_Stack_Frame() */ 00081 #include "opt_alias_interface.h" /* for ALIAS_MANAGER stuff */ 00082 #include "wn_lower.h" /* for WN_Lower() */ 00083 #include "ori.h" /* for Olimit_Region_Insertion */ 00084 #include "w2c_driver.h" /* for W2C_Process_Command_Line, etc. */ 00085 #include "w2f_driver.h" /* for W2F_Process_Command_Line, etc. */ 00086 #include "anl_driver.h" /* for Anl_Process_Command_Line, etc. */ 00087 #include "region_util.h" /* for Regions_Around_Inner_Loops */ 00088 #include "region_main.h" /* for REGION_* driver specific routines */ 00089 #include "tracing.h" /* For the trace routines */ 00090 #include "ir_reader.h" /* For fdump_tree */ 00091 #include "dwarf_DST.h" /* for Orig_PU_Name */ 00092 #include "fb_whirl.h" /* for FEEDBACK */ 00093 #include "iter.h" /* PU iterator for loops */ 00094 #include "dra_export.h" /* for DRA routines */ 00095 #include "ti_init.h" /* for targ_info */ 00096 #include "opt_alias_interface.h" /* for Create_Alias_Manager */ 00097 #include "omp_lower.h" /* for OMP pre-lowering interface */ 00098 #include "cxx_memory.h" /* CXX_NEW */ 00099 #include "options_stack.h" /* for Options_Stack */ 00100 #include "be_symtab.h" /* for Be_preg_tab */ 00101 #include "prompf.h" /* Prompf support */ 00102 #include "wb_omp.h" /* whirl browser for omp prelowerer */ 00103 #include "wb_lwr.h" /* whirl browser for lowerer */ 00104 #include "wb_anl.h" /* whirl browser for prompf static anal */ 00105 #include "wn_instrument.h" /* whirl instrumenter */ 00106 #include "mem_ctr.h" 00107 #include "upc_symtab_utils.h" 00108 #include "ipl_driver.h" 00109 00110 00111 #if defined(__CYGWIN__) 00112 # define DSOext ".dll" /* cygwin needs to use dll for DSOs */ 00113 #else 00114 # define DSOext ".so" 00115 #endif 00116 00117 00118 extern void Initialize_Targ_Info(void); 00119 00120 #if defined(_GCC_NO_PRAGMAWEAK) || defined(__CYGWIN__) 00121 extern "C" { 00122 INT64 New_Construct_Id(void) { return 0; } 00123 INT64 Get_Next_Construct_Id(void) { return 0; } 00124 } 00125 #endif 00126 00127 00128 // symbols defined in wopt.so 00129 #if defined(__linux__) || defined(_GCC_NO_PRAGMAWEAK) || defined(__CYGWIN__) 00130 00131 extern void (*wopt_main_p) (INT argc, char **argv, INT, char **); 00132 #define wopt_main (*wopt_main_p) 00133 00134 extern void (*Wopt_Init_p) (); 00135 #define Wopt_Init (*Wopt_Init_p) 00136 00137 extern void (*Wopt_Fini_p) (); 00138 #define Wopt_Fini (*Wopt_Fini_p) 00139 00140 extern WN* (*Perform_Preopt_Optimization_p) (WN *, WN *); 00141 #define Perform_Preopt_Optimization (*Perform_Preopt_Optimization_p) 00142 00143 extern WN* (*Perform_Global_Optimization_p) (WN *, WN *, ALIAS_MANAGER *); 00144 #define Perform_Global_Optimization (*Perform_Global_Optimization_p) 00145 00146 extern WN* (*Pre_Optimizer_p) (INT32, WN*, DU_MANAGER*, ALIAS_MANAGER*); 00147 #define Pre_Optimizer (*Pre_Optimizer_p) 00148 00149 extern DU_MANAGER* (*Create_Du_Manager_p) (MEM_POOL *); 00150 #define Create_Du_Manager (*Create_Du_Manager_p) 00151 00152 extern void (*Delete_Du_Manager_p) (DU_MANAGER *, MEM_POOL *); 00153 #define Delete_Du_Manager (*Delete_Du_Manager_p) 00154 00155 extern BOOL (*Verify_alias_p) (ALIAS_MANAGER *, WN *); 00156 #define Verify_alias (*Verify_alias_p) 00157 00158 #else 00159 00160 #pragma weak wopt_main 00161 #pragma weak Wopt_Init 00162 #pragma weak Wopt_Fini 00163 #pragma weak Perform_Global_Optimization 00164 #pragma weak Perform_Preopt_Optimization 00165 #pragma weak Pre_Optimizer 00166 #pragma weak Create_Du_Manager 00167 #pragma weak Delete_Du_Manager 00168 #pragma weak Verify_alias 00169 00170 #endif // __linux__ 00171 00172 00173 // symbols defined in lno.so 00174 #if defined(__linux__) || defined(_GCC_NO_PRAGMAWEAK) || defined(__CYGWIN__) 00175 00176 extern void (*lno_main_p) (INT, char**, INT, char**); 00177 #define lno_main (*lno_main_p) 00178 00179 extern void (*Lno_Init_p) (); 00180 #define Lno_Init (*Lno_Init_p) 00181 00182 extern void (*Lno_Fini_p) (); 00183 #define Lno_Fini (*Lno_Fini_p) 00184 00185 extern WN* (*Perform_Loop_Nest_Optimization_p) (PU_Info*, WN*, WN*, BOOL); 00186 #define Perform_Loop_Nest_Optimization (*Perform_Loop_Nest_Optimization_p) 00187 00188 #else 00189 00190 #pragma weak lno_main 00191 #pragma weak Lno_Init 00192 #pragma weak Lno_Fini 00193 #pragma weak Perform_Loop_Nest_Optimization 00194 00195 #endif // __linux__ 00196 00197 00198 // symbols defined in ipl.so 00199 #if defined(__linux__) || defined(_GCC_NO_PRAGMAWEAK) || defined(__CYGWIN__) 00200 00201 extern void (*Ipl_Extra_Output_p) (Output_File *); 00202 #define Ipl_Extra_Output (*Ipl_Extra_Output_p) 00203 00204 extern void (*Ipl_Init_p) (); 00205 #define Ipl_Init (*Ipl_Init_p) 00206 00207 extern void (*Ipl_Fini_p) (); 00208 #define Ipl_Fini (*Ipl_Fini_p) 00209 00210 extern void (*ipl_main_p) (INT, char **); 00211 #define ipl_main (*ipl_main_p) 00212 00213 extern void (*Perform_Procedure_Summary_Phase_p) (WN*, DU_MANAGER*, 00214 ALIAS_MANAGER*, void*); 00215 #define Perform_Procedure_Summary_Phase (*Perform_Procedure_Summary_Phase_p) 00216 00217 #else 00218 00219 #pragma weak ipl_main 00220 #pragma weak Ipl_Init 00221 #pragma weak Ipl_Fini 00222 #pragma weak Ipl_Extra_Output 00223 #pragma weak Perform_Procedure_Summary_Phase 00224 00225 #endif // __linux__ 00226 00227 00228 #include "w2c_weak.h" 00229 #include "w2f_weak.h" 00230 00231 00232 #if defined(_GCC_NO_PRAGMAWEAK) || defined(__CYGWIN__) 00233 00234 extern "C" { 00235 void Anl_Process_Command_Line (INT phase_argc, char *phase_argv[], 00236 INT argc, char *argv[]) { } 00237 BOOL Anl_Needs_Whirl2c(void) { return false; } 00238 BOOL Anl_Needs_Whirl2f(void) { return false; } 00239 void Anl_Init(void) { } 00240 WN_MAP Anl_Init_Map(MEM_POOL *id_map_pool) { return NULL; } 00241 void Anl_Static_Analysis(WN *pu, WN_MAP id_map) { } 00242 const char *Anl_File_Path(void) { return NULL; } 00243 void Anl_Fini(void) { } 00244 void Anl_Cleanup(void){ } 00245 } 00246 00247 void Prompf_Emit_Whirl_to_Source(PU_Info* current_pu, 00248 WN* func_nd) { } 00249 00250 #else 00251 00252 #pragma weak Anl_Cleanup 00253 #pragma weak Anl_Process_Command_Line 00254 #pragma weak Anl_Needs_Whirl2c 00255 #pragma weak Anl_Needs_Whirl2f 00256 #pragma weak Anl_Init 00257 #pragma weak Anl_Init_Map 00258 #pragma weak Anl_Static_Analysis 00259 #pragma weak Anl_Fini 00260 00261 #endif 00262 00263 00264 /* Solaris CC porting 00265 * Solaris CC #pragma weak can be either followed by one mangled name in 00266 * string form, or followed by two mangled names. A better way is to 00267 * define an Asserta and let these weak functions to equal to Asserta 00268 */ 00269 #if !defined(__GNUC__) && defined(_SOLARIS_SOLARIS) 00270 # pragma weak "__1cbBPrompf_Emit_Whirl_to_Source6FpnHpu_info_pnCWN__v_" 00271 #elif !defined(__GNUC__) 00272 # pragma weak Prompf_Emit_Whirl_to_Source__GP7pu_infoP2WN 00273 #else 00274 # pragma weak Prompf_Emit_Whirl_to_Source__FP7pu_infoP2WN 00275 00276 /* FIXME */ 00277 # if defined(_LINUX_LINUX) && !defined(__CYGWIN__) \ 00278 && defined(__GNUC__) && (__GNUC__ >= 3) 00279 void Prompf_Emit_Whirl_to_Source(PU_Info* current_pu, WN* func_nd) { } 00280 # endif 00281 #endif 00282 00283 extern void Prompf_Emit_Whirl_to_Source(PU_Info* current_pu, WN* func_nd); 00284 00285 00286 static INT ecount = 0; 00287 static BOOL need_wopt_output = FALSE; 00288 static BOOL need_lno_output = FALSE; 00289 static BOOL need_ipl_output = FALSE; 00290 static Output_File *ir_output = 0; 00291 00292 // options stack for PU and region level pragmas 00293 static OPTIONS_STACK *Options_Stack; 00294 00295 static BOOL reset_opt_level = FALSE; 00296 static struct ALIAS_MANAGER *alias_mgr = NULL; 00297 00298 static BOOL Run_Distr_Array = FALSE; 00299 BOOL Run_MemCtr = FALSE; 00300 00301 static BOOL Saved_run_prompf = FALSE; /* TODO: Remove when uses are removed */ 00302 static BOOL Saved_run_w2c = FALSE; /* TODO: Remove */ 00303 static BOOL Saved_run_w2f = FALSE; /* TODO: Remove */ 00304 static BOOL Saved_run_w2fc_early = FALSE; /* TODO: Remove */ 00305 00306 extern WN_MAP Prompf_Id_Map; /* Maps WN constructs to unique identifiers */ 00307 00308 /* Keep track of which optional components are loaded, where we need 00309 * to do so. 00310 */ 00311 static BOOL wopt_loaded = FALSE; 00312 extern BOOL Prompf_anl_loaded; /* Defined in cleanup.c */ 00313 extern BOOL Purple_loaded; /* Defined in cleanup.c */ 00314 extern BOOL Whirl2f_loaded; /* Defined in cleanup.c */ 00315 extern BOOL Whirl2c_loaded; /* Defined in cleanup.c */ 00316 00317 extern void *Current_Dep_Graph; 00318 FILE *DFile = stderr; 00319 00320 //Default Sizes (in bytes) for shared ptr, reg, memory handle, etc. 00321 int s_size = 16, p_size = 16, r_size = 4, m_size = 4; 00322 00323 static void 00324 load_components (INT argc, char **argv) 00325 { 00326 INT phase_argc; 00327 char **phase_argv; 00328 00329 if (Run_cg || Run_lno || Run_autopar) { 00330 // initialize target-info before cg or lno 00331 Initialize_Targ_Info(); 00332 } 00333 00334 if (!(Run_lno || Run_wopt || Run_preopt || Run_cg || 00335 Run_prompf || Run_purple || Run_w2c || Run_w2f 00336 || Run_w2fc_early || Run_ipl)) 00337 Run_cg = TRUE; /* if nothing is set, run CG */ 00338 00339 if (Run_ipl) { 00340 Run_lno = Run_wopt = Run_cg = Run_w2fc_early 00341 = Run_prompf = Run_purple = Run_w2c = Run_w2f = FALSE; 00342 } 00343 00344 if (Run_prompf || Run_w2fc_early) { 00345 Get_Phase_Args (PHASE_PROMPF, &phase_argc, &phase_argv); 00346 load_so("prompf_anl" DSOext, Prompf_Anl_Path, Show_Progress); 00347 Prompf_anl_loaded = TRUE; 00348 Anl_Process_Command_Line(phase_argc, phase_argv, argc, argv); 00349 } 00350 00351 if (Run_w2f) 00352 { 00353 Get_Phase_Args (PHASE_W2F, &phase_argc, &phase_argv); 00354 load_so("whirl2f" DSOext, W2F_Path, Show_Progress); 00355 Whirl2f_loaded = TRUE; 00356 if (Run_prompf) 00357 W2F_Set_Prompf_Emission(&Prompf_Id_Map); 00358 00359 W2F_Process_Command_Line(phase_argc, phase_argv, argc, argv); 00360 } 00361 } /* load_components */ 00362 00363 00364 /* phase-specific initializations that need to be done after reading 00365 * in the global symbol tables. 00366 */ 00367 static void 00368 Phase_Init (void) 00369 { 00370 char *output_file_name = Obj_File_Name; 00371 00372 if (Run_Distr_Array && 00373 (Run_w2c || Run_w2f) && 00374 !Run_lno && 00375 !Run_wopt && 00376 !Run_cg) 00377 { 00378 /* A special case, where it looks as though we only wish to 00379 * run some early phases and then put out the flist or clist. 00380 * Disable the turning on of subsequent phases due to the 00381 * Run_Distr_Array flag. 00382 */ 00383 Run_Distr_Array = FALSE; 00384 } 00385 if ( LNO_Run_Lego_Set && ( LNO_Run_Lego == FALSE ) ) 00386 Run_Distr_Array = FALSE; 00387 00388 if (Run_w2c || (Run_prompf && Anl_Needs_Whirl2c())) 00389 W2C_Outfile_Init (TRUE/*emit_global_decls*/); 00390 if (Run_w2f || (Run_prompf && Anl_Needs_Whirl2f())) 00391 W2F_Outfile_Init (); 00392 if (Run_prompf) 00393 Anl_Init (); 00394 /* Must be done after w2c and w2f */ 00395 if ((Run_lno || Run_preopt) && !Run_cg && !Run_wopt) 00396 need_lno_output = TRUE; 00397 if (Run_wopt && !Run_cg) 00398 need_wopt_output = TRUE; 00399 00400 if (Run_ipl) { 00401 need_ipl_output = TRUE; 00402 need_lno_output = need_wopt_output = FALSE; 00403 } 00404 00405 if (output_file_name == 0) { 00406 if (Src_File_Name) 00407 output_file_name = Last_Pathname_Component (Src_File_Name); 00408 else 00409 output_file_name = Irb_File_Name; 00410 } 00411 00412 if (need_lno_output) { 00413 Write_BE_Maps = TRUE; 00414 ir_output = Open_Output_Info(New_Extension(output_file_name,".N")); 00415 } 00416 if (need_wopt_output) { 00417 Write_ALIAS_CLASS_Map = TRUE; 00418 Write_BE_Maps = TRUE; 00419 ir_output = Open_Output_Info(New_Extension(output_file_name,".O")); 00420 } 00421 if (need_ipl_output) { 00422 Write_BE_Maps = FALSE; 00423 ir_output = Open_Output_Info (Obj_File_Name ? 00424 Obj_File_Name : 00425 New_Extension(output_file_name, ".o")); 00426 } 00427 if (Emit_Global_Data) { 00428 Write_BE_Maps = FALSE; 00429 ir_output = Open_Output_Info (Global_File_Name); 00430 } 00431 00432 } /* Phase_Init */ 00433 00434 00435 static void 00436 Phase_Fini (void) 00437 { 00438 CURRENT_SYMTAB = GLOBAL_SYMTAB; 00439 00440 /* Always finish prompf analysis file, purple, w2c and w2f first */ 00441 if (Run_prompf) 00442 Anl_Fini(); 00443 if (Run_w2f || (Run_prompf && Anl_Needs_Whirl2f())) 00444 W2F_Outfile_Fini (); 00445 Verify_SYMTAB (CURRENT_SYMTAB); /* Verifies global SYmtab */ 00446 } /* Phase_Fini */ 00447 00448 /* static */ char * 00449 Get_Orig_PU_Name (PU_Info * current_pu) 00450 { 00451 DST_IDX dst; 00452 DST_INFO *info; 00453 DST_SUBPROGRAM *PU_attr; 00454 00455 dst = PU_Info_pu_dst(current_pu); 00456 00457 if (DST_IS_NULL (dst)) { 00458 return ST_name(PU_Info_proc_sym(current_pu)); 00459 } 00460 00461 info = DST_INFO_IDX_TO_PTR (dst); 00462 00463 if ( (DST_INFO_tag(info) != DW_TAG_subprogram) 00464 || DST_IS_declaration(DST_INFO_flag(info)) ) 00465 { 00466 return ST_name(PU_Info_proc_sym(current_pu)); 00467 } 00468 PU_attr = DST_ATTR_IDX_TO_PTR(DST_INFO_attributes(info), DST_SUBPROGRAM); 00469 if (PU_attr->def.name.byte_idx < 0) { 00470 return NULL; 00471 /* Why not the following line instead? -- RK 960808 00472 * return ST_name(PU_Info_proc_sym(current_pu)); 00473 */ 00474 } 00475 return DST_STR_IDX_TO_PTR(DST_SUBPROGRAM_def_name(PU_attr)); 00476 } 00477 00478 static void 00479 Save_Cur_PU_Name (char *name, INT rid_id) 00480 { 00481 if ( Cur_PU_Name == NULL ) { 00482 /* ST_name will return a pointer into the symbol table, which is 00483 * mmap-ed. This causes a problem in the error message routines 00484 * when an unexpected signal occurs, because as part of the cleanup 00485 * files are closed. To fix the problem we just allocate some 00486 * memory and make a copy. 00487 * Allocate 8 extra bytes to leave room for RGN suffix. 00488 */ 00489 Cur_PU_Name = TYPE_MEM_POOL_ALLOC_N(char, &MEM_pu_nz_pool, 00490 strlen(name) + 8); 00491 Cur_PU_Name = strcpy(Cur_PU_Name, name); 00492 } 00493 if (rid_id != 0) { 00494 /* add RGN suffix */ 00495 sprintf(Cur_PU_Name,"%s.RGN%03d", name, rid_id); 00496 } 00497 else if (strlen(name) != strlen(Cur_PU_Name)) { 00498 /* clear RGN suffix */ 00499 Cur_PU_Name = strcpy(Cur_PU_Name, name); 00500 } 00501 } 00502 00503 00504 // Adjust/Lower optimization level based on 00505 // 1. size of PU and Olimit 00506 // 2. existence of non-ANSI setjmp calls 00507 // 00508 static WN * 00509 Adjust_Opt_Level (PU_Info* current_pu, WN *pu, char *pu_name) 00510 { 00511 INT new_opt_level = 0; 00512 COMPUTE_PU_OLIMIT; 00513 00514 if (Get_Trace(TKIND_INFO, TINFO_STATS)) { 00515 /* Print Olimit stats to trace file: */ 00516 INT PU_Var_Cnt = ST_Table_Size (CURRENT_SYMTAB) + 00517 PREG_Table_Size (CURRENT_SYMTAB); 00518 fprintf (TFile, "PU_Olimit for %s is %d (bbs=%d,stms=%d,vars=%d)\n", 00519 pu_name, PU_Olimit, PU_WN_BB_Cnt, PU_WN_Stmt_Cnt, PU_Var_Cnt); 00520 } 00521 00522 if ((Opt_Level > 0 || Run_autopar) && PU_Olimit > Olimit && !Olimit_opt) { 00523 if (Show_OPT_Warnings) 00524 ErrMsg (EC_Olimit_Exceeded, pu_name, PU_Olimit); 00525 reset_opt_level = TRUE; 00526 } 00527 if (((Opt_Level > 0 || Run_autopar) || Olimit_opt) 00528 && Query_Skiplist ( Optimization_Skip_List, Current_PU_Count() ) ) 00529 { 00530 if (Show_OPT_Warnings) 00531 ErrMsg (EC_Not_Optimized, pu_name, Current_PU_Count() ); 00532 reset_opt_level = TRUE; 00533 } 00534 if (/* !LANG_Ansi_Setjmp_On && */ 00535 /* 1. Cannot check LANG_Ansi_Setjmp_On because IPA does not pass -LANG group. 00536 2. The ST_pu_calls_setjmp is not set unless LANG_Ansi_Setjmp_On = false */ 00537 PU_calls_setjmp (Get_Current_PU ())) { 00538 reset_opt_level = TRUE; 00539 new_opt_level = 1; 00540 ErrMsg (EC_Not_Ansi_Setjmp, pu_name, Current_PU_Count(), new_opt_level ); 00541 } 00542 if (reset_opt_level) { 00543 Opt_Level = new_opt_level; 00544 Run_lno = Run_preopt = Run_wopt = Run_autopar = FALSE; 00545 alias_mgr = NULL; 00546 Olimit_opt = FALSE; 00547 if (Run_prompf) 00548 Prompf_Emit_Whirl_to_Source(current_pu, pu); 00549 } 00550 00551 return pu; 00552 } /* Adjust_Opt_Level */ 00553 00554 /* Misc. processing after LNO is done, PU exists as a whole during this 00555 procedure */ 00556 static void 00557 Post_LNO_Processing (PU_Info *current_pu, WN *pu) 00558 { 00559 BOOL is_user_visible_pu = (CURRENT_SYMTAB == GLOBAL_SYMTAB + 1) || 00560 ((Language == LANG_F90) && 00561 (CURRENT_SYMTAB == GLOBAL_SYMTAB + 2) && 00562 (!Is_Set_PU_Info_flags(current_pu, PU_IS_COMPILER_GENERATED))) ; 00563 00564 /* Only run w2c and w2f on top-level PUs, unless otherwise requested. 00565 */ 00566 if (Run_w2c && !Run_w2fc_early && !Run_prompf) { 00567 if (W2C_Should_Emit_Nested_PUs() || is_user_visible_pu) { 00568 W2C_Outfile_Translate_Pu(pu, TRUE/*emit_global_decls*/); 00569 } 00570 } 00571 if (Run_w2f && !Run_w2fc_early && !Run_prompf) { 00572 if (W2F_Should_Emit_Nested_PUs() || is_user_visible_pu) { 00573 if (PU_need_unparsed(ST_pu(WN_st(pu)))) 00574 W2F_Outfile_Translate_Pu(pu); 00575 } 00576 } 00577 00578 /* only write .N file for PU, no need to replace region because 00579 REGION_remove_and_mark does nothing for pu (rwn is the pu) */ 00580 if (need_lno_output) { 00581 Set_PU_Info_tree_ptr(current_pu, pu); 00582 Write_PU_Info(current_pu); 00583 Verify_SYMTAB (CURRENT_SYMTAB); 00584 } 00585 00586 } /* Post_LNO_Processing */ 00587 00588 00589 extern "C" { 00590 extern void Process_Fill_Align_Pragmas (WN* func_wn); 00591 extern void Rewrite_Pragmas_On_Structs (WN* block_wn, WN* wn); 00592 } 00593 00594 /*********************************************************************** 00595 * 00596 * Find all EH regions in the PU, and mark their INITOs as used. 00597 * 00598 ***********************************************************************/ 00599 static void Update_EHRegion_Inito_Used (WN *wn) { 00600 if (!wn) return; 00601 00602 OPERATOR opr = WN_operator(wn); 00603 00604 if (opr == OPR_REGION && WN_ereg_supp(wn)) { 00605 INITO_IDX ino_idx = WN_ereg_supp(wn); 00606 ST *st = INITO_st(ino_idx); 00607 Clear_ST_is_not_used(st); 00608 } 00609 00610 // now recurse 00611 if (opr == OPR_BLOCK) { 00612 WN *kid = WN_first (wn); 00613 while (kid) { 00614 Update_EHRegion_Inito_Used(kid); 00615 kid = WN_next(kid); 00616 } 00617 } else { 00618 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) { 00619 Update_EHRegion_Inito_Used(WN_kid(wn,kidno)); 00620 } 00621 } 00622 } 00623 00624 /*********************************************************************** 00625 * 00626 * This pass is called after preopt+lno+mplowering. 00627 * Any of those passes may have deleted EH-regions, but left the 00628 * INITO sts for those regions hanging around. 00629 * This pass will search for all used INITOs, and mark the rest unused. 00630 * 00631 ***********************************************************************/ 00632 static void Update_EHRegion_Inito (WN *pu) { 00633 INT i; 00634 INITO *ino; 00635 00636 // first mark all EH-region STs unused. 00637 FOREACH_INITO (CURRENT_SYMTAB, ino, i) { 00638 ST *st = INITO_st(ino); 00639 if (ST_sclass(st) == SCLASS_EH_REGION || 00640 ST_sclass(st) == SCLASS_EH_REGION_SUPP) { 00641 Set_ST_is_not_used(st); 00642 } 00643 } 00644 00645 // now find INITO sts that are referenced in WHIRL, 00646 // and mark them used. 00647 Update_EHRegion_Inito_Used (pu); 00648 } 00649 00650 static void 00651 Backend_Processing (PU_Info *current_pu, WN *pu) 00652 { 00653 { 00654 /* Always process the first PU for fill-align, since that one contains 00655 * the pragmas for global symbols. And, because of IPA, we cannot 00656 * depend on the SYMTAB_id being 1 for the first PU. 00657 */ 00658 static BOOL done_first_pu = FALSE; 00659 BOOL needs_fill_align_lowering = 00660 PU_needs_fill_align_lowering (Get_Current_PU ()); 00661 if (needs_fill_align_lowering || !done_first_pu) { 00662 Process_Fill_Align_Pragmas (pu); 00663 done_first_pu = TRUE; 00664 } 00665 } 00666 00667 PU_adjust_addr_flags(Get_Current_PU_ST(), pu); 00668 00669 if (Run_MemCtr) 00670 MemCtr_Add (pu); 00671 00672 /* Make sure that RETURN_VAL nodes, Return_Val_Preg references and 00673 MLDID/MSTID nodes have been lowered. This requires its own pass 00674 because it may have to go back to change the previous CALL statement 00675 to add a fake parameter. */ 00676 if (WHIRL_Return_Val_On || WHIRL_Mldid_Mstid_On) { 00677 Is_True(WHIRL_Return_Val_On && WHIRL_Mldid_Mstid_On, 00678 ("-INTERNAL:return_val and -INTERNAL:mldid_mstid must be on the same time")); 00679 } 00680 00681 /* First round output (.N file, w2c, w2f, etc.) */ 00682 Set_Error_Phase ( "Post LNO Processing" ); 00683 Post_LNO_Processing (current_pu, pu); 00684 00685 return; 00686 } /* Backend_Processing */ 00687 00688 static WN * 00689 Preprocess_PU (PU_Info *current_pu) 00690 { 00691 WN *pu = NULL; 00692 00693 Initialize_PU_Stats (); /* Needed for Olimit as well as tracing */ 00694 00695 Current_PU_Info = current_pu; 00696 MEM_POOL_Push(MEM_pu_nz_pool_ptr); 00697 MEM_POOL_Push(MEM_pu_pool_ptr); 00698 00699 BOOL is_mp_nested_pu = FALSE; 00700 00701 /* read from mmap area */ 00702 Start_Timer ( T_ReadIR_CU ); 00703 // The current PU could already be memory as happens when the 00704 // compiler creates it during back end compilation of an earlier PU. 00705 if (PU_Info_state (current_pu, WT_TREE) != Subsect_InMem) { 00706 Read_Local_Info (MEM_pu_nz_pool_ptr, current_pu); 00707 } else { /* retrieve transferred maps */ 00708 // change some globals to define current_pu as the current PU 00709 Current_Map_Tab = PU_Info_maptab(current_pu); 00710 Current_pu = &PU_Info_pu(current_pu); 00711 CURRENT_SYMTAB = PU_lexical_level(*Current_pu); 00712 if ((PU_is_nested_func(*Current_pu) && PU_mp(*Current_pu)) || 00713 Is_Set_PU_Info_flags(current_pu, PU_IS_DRA_CLONE)) { 00714 is_mp_nested_pu = TRUE; 00715 // hack to restore nested PU's symtab 00716 Restore_Local_Symtab(current_pu); 00717 } else { 00718 Is_True(FALSE, ("Robert doesn't understand where symtabs come from")); 00719 } 00720 } 00721 00722 BE_symtab_alloc_scope_level(CURRENT_SYMTAB); 00723 Scope_tab[CURRENT_SYMTAB].st_tab->Register(*Be_scope_tab[CURRENT_SYMTAB].be_st_tab); 00724 00725 /* NOTE: "pu" is not defined until this point, since the actual 00726 * (WN *) is calculated by Read_Local_Info(). 00727 */ 00728 pu = PU_Info_tree_ptr(current_pu); 00729 00730 /* Disable all prompf processing for PUs generated by the compiler, 00731 * such as cloned subroutines, with exception of mp routines which 00732 * we do want to process (we just don't want to do the static 00733 * analysis part for them). 00734 * 00735 * TODO: Disable Anl_Static_Analysis() when this condition holds, 00736 * but generate the subroutines in the .m file and have the cloner 00737 * assign an ID map for the subroutine with unique ID numbers. 00738 */ 00739 if (!Saved_run_prompf && 00740 Run_prompf && 00741 Is_Set_PU_Info_flags(current_pu, PU_IS_COMPILER_GENERATED) && 00742 !PU_mp (Get_Current_PU ())) { 00743 Saved_run_prompf = Run_prompf; 00744 Saved_run_w2c = Run_w2c; 00745 Saved_run_w2f = Run_w2f; 00746 Saved_run_w2fc_early = Run_w2fc_early; 00747 Run_prompf = FALSE; 00748 Run_w2c = FALSE; 00749 Run_w2f = FALSE; 00750 Run_w2fc_early = FALSE; 00751 } 00752 00753 /* store original pu name */ 00754 Orig_PU_Name = Get_Orig_PU_Name(current_pu); 00755 Save_Cur_PU_Name(ST_name(PU_Info_proc_sym(current_pu)), 0); 00756 00757 Set_Current_PU_For_Trace(ST_name(PU_Info_proc_sym(current_pu)), 00758 Current_PU_Count()); 00759 00760 Stop_Timer (T_ReadIR_CU); 00761 Check_for_IR_Dump(TP_IR_READ,pu,"IR_READ"); 00762 00763 if (Show_Progress) { 00764 fprintf(stderr, "Compiling %s(%d)\n", 00765 ST_name(PU_Info_proc_sym(current_pu)), 00766 Current_PU_Count()); 00767 } 00768 00769 if (Get_Trace(TP_REGION,TT_REGION_ALL)) { 00770 fprintf(TFile,"===== BE driver, PU loop: PU %s(%d)\n", 00771 ST_name(PU_Info_proc_sym(current_pu)),Current_PU_Count()); 00772 } 00773 00774 if (Tlog_File) { 00775 fprintf(Tlog_File,"BEGIN %s\n",ST_name(PU_Info_proc_sym(current_pu))); 00776 } 00777 00778 WN_Mem_Push (); 00779 00780 pu = Adjust_Opt_Level (current_pu, pu, ST_name(PU_Info_proc_sym(current_pu))); 00781 00782 return pu; 00783 } /* Preprocess_PU */ 00784 00785 static void 00786 Postprocess_PU (PU_Info *current_pu) 00787 { 00788 if (Tlog_File) { 00789 fprintf (Tlog_File, "END %s\n", ST_name(PU_Info_proc_sym(current_pu))); 00790 } 00791 00792 Current_Map_Tab = PU_Info_maptab(current_pu); 00793 00794 // Delete alias manager after CG finished ? PV 525127, 527977 00795 WN_Mem_Pop (); // WN pool 00796 00797 00798 SYMTAB_IDX scope_level = PU_lexical_level(PU_Info_pu(current_pu)); 00799 00800 Scope_tab[scope_level].st_tab-> 00801 Un_register(*Be_scope_tab[scope_level].be_st_tab); 00802 Be_scope_tab[scope_level].be_st_tab->Clear(); 00803 00804 Free_Local_Info(current_pu); // deletes all maps 00805 MEM_POOL_Pop(MEM_pu_nz_pool_ptr); 00806 MEM_POOL_Pop(MEM_pu_pool_ptr); 00807 00808 /* Re-enable prompf processing if relevant. 00809 * 00810 * TODO: Disable Anl_Static_Analysis() when this condition holds, 00811 * but generate the subroutines in the .m file and have the cloner 00812 * assign an ID map for the subroutine with unique ID numbers. 00813 */ 00814 if (Saved_run_prompf) { 00815 Run_prompf = Saved_run_prompf; 00816 Run_w2c = Saved_run_w2c; 00817 Run_w2f = Saved_run_w2f; 00818 Run_w2fc_early = Saved_run_w2fc_early; 00819 Saved_run_prompf = FALSE; 00820 Saved_run_w2c = FALSE; 00821 Saved_run_w2f = FALSE; 00822 Saved_run_w2fc_early = FALSE; 00823 } 00824 } /* Postprocess_PU */ 00825 00826 /* compile each PU through all phases before going to the next PU */ 00827 static void 00828 Preorder_Process_PUs (PU_Info *current_pu) 00829 { 00830 INT orig_opt_level = Opt_Level; 00831 BOOL orig_run_lno = Run_lno; 00832 BOOL orig_run_preopt = Run_preopt; 00833 BOOL orig_run_wopt = Run_wopt; 00834 BOOL orig_olimit_opt = Olimit_opt; 00835 00836 WN *pu; 00837 Start_Timer(T_BE_PU_CU); 00838 00839 pu = Preprocess_PU(current_pu); 00840 00841 00842 // Quick! Before anyone risks creating any PREGs in the back end, 00843 // register the back end's PREG table with the main PREG table so 00844 // they will grow together as PREGs are created. 00845 Scope_tab[CURRENT_SYMTAB].preg_tab->Register(Be_preg_tab); 00846 00847 WN_verifier(pu); 00848 00849 Verify_SYMTAB (CURRENT_SYMTAB); 00850 00851 Backend_Processing (current_pu, pu); 00852 Verify_SYMTAB (CURRENT_SYMTAB); 00853 00854 if (reset_opt_level) { 00855 Opt_Level = orig_opt_level; 00856 Run_lno = orig_run_lno; 00857 Run_preopt = orig_run_preopt; 00858 Run_wopt = orig_run_wopt; 00859 reset_opt_level = FALSE; 00860 Olimit_opt = orig_olimit_opt; 00861 } 00862 00863 Scope_tab[CURRENT_SYMTAB].preg_tab->Un_register(Be_preg_tab); 00864 Be_preg_tab.Clear(); 00865 00866 Stop_Timer(T_BE_PU_CU); 00867 Finish_BE_Timing ( Tim_File, ST_name(PU_Info_proc_sym(current_pu)) ); 00868 Advance_Current_PU_Count(); 00869 00870 Cur_PU_Name = NULL; // memory will not be leaked; eventual 00871 // pop occurs in Postprocess_PU's call 00872 // to WN_MEM_Pop. Reset here is 00873 // required so Save_Cur_PU_Name will 00874 // not misbehave. 00875 00876 // Print miscellaneous statistics to trace file: 00877 Print_PU_Stats (); 00878 00879 // Now recursively process the child PU's. 00880 00881 for (PU_Info *child = PU_Info_child(current_pu); 00882 child != NULL; 00883 child = PU_Info_next(child)) { 00884 Preorder_Process_PUs(child); 00885 } 00886 00887 Postprocess_PU (current_pu); 00888 } /* Preorder_Process_PUs */ 00889 00890 static void Print_Tlog_Header(INT argc, char **argv) 00891 { 00892 INT i; 00893 if (Get_Trace(TP_PTRACE1, TP_PTRACE1_NOHDR)) 00894 return; 00895 fprintf(Tlog_File,"1.0\n"); /* initial version number */ 00896 fprintf(Tlog_File,"{ "); 00897 for (i=0; i<argc; i++) 00898 fprintf(Tlog_File,"%s ", argv[i]); 00899 fprintf(Tlog_File,"}\n"); 00900 } 00901 00902 00903 #define FEEDBACK_PATH_MAXLEN 1024 00904 00905 00906 // Provide a place to stop after components are loaded 00907 extern "C" { 00908 void be_debug(void) {} 00909 } 00910 00911 00912 void RiceWhirl2f (INT * argc, char * **argv); 00913 00914 00915 00916 INT 00917 main (INT argc, char **argv) 00918 { 00919 INT local_ecount, local_wcount; 00920 PU_Info *pu_tree; 00921 00922 00923 setlinebuf (stdout); 00924 setlinebuf (stderr); 00925 Handle_Signals (); 00926 MEM_Initialize (); 00927 Cur_PU_Name = NULL; 00928 Init_Error_Handler ( 100 ); 00929 Set_Error_Line ( ERROR_LINE_UNKNOWN ); 00930 Set_Error_File ( NULL ); 00931 Set_Error_Phase ( "Back End Driver" ); 00932 Preconfigure (); 00933 00934 RiceWhirl2f ( & argc, & argv); 00935 00936 Process_Command_Line (argc, argv); 00937 00938 if (Inhibit_EH_opt && Opt_Level > 1) Opt_Level = 1; 00939 Reset_Timers (); 00940 Start_Timer(T_BE_Comp); 00941 Prepare_Source (); 00942 Initialize_Stats (); 00943 00944 Configure (); 00945 Configure_Source(NULL); /* Most configuration variables are set here */ 00946 #ifdef Is_True_On 00947 if (Get_Trace (TKIND_ALLOC, TP_MISC)) { 00948 MEM_Tracing_Enable(); 00949 } 00950 #endif 00951 if ( List_Enabled ) { 00952 Prepare_Listing_File (); 00953 List_Compile_Options ( Lst_File, "", FALSE, List_All_Options, FALSE ); 00954 } 00955 00956 Init_Operator_To_Opcode_Table(); 00957 00958 00959 00960 /* decide which phase to call */ 00961 load_components (argc, argv); 00962 be_debug(); 00963 00964 MEM_POOL_Push (&MEM_src_pool); 00965 MEM_POOL_Push (&MEM_src_nz_pool); 00966 if ( Show_Progress ) { 00967 fprintf ( stderr, "Compiling %s (%s) -- Back End\n", 00968 Src_File_Name, Irb_File_Name ); 00969 fflush ( stderr ); 00970 } 00971 Set_Error_Source (Src_File_Name); 00972 00973 // Push initial file level options 00974 Options_Stack = CXX_NEW(OPTIONS_STACK(&MEM_src_nz_pool), &MEM_src_nz_pool); 00975 Options_Stack->Push_Current_Options(); 00976 00977 Start_Timer (T_ReadIR_Comp); 00978 00979 if (Read_Global_Data) { 00980 // get input from two separate files 00981 Irb_File = (FILE *)Open_Global_Input (Global_File_Name); 00982 Irb_File = (FILE *)Open_Local_Input (Irb_File_Name); 00983 } 00984 else { 00985 Irb_File = (FILE *)Open_Input_Info (Irb_File_Name); 00986 } 00987 Initialize_Symbol_Tables (FALSE); 00988 New_Scope (GLOBAL_SYMTAB, Malloc_Mem_Pool, FALSE); 00989 pu_tree = Read_Global_Info (NULL); 00990 Stop_Timer (T_ReadIR_Comp); 00991 00992 Initialize_Special_Global_Symbols (); 00993 00994 // if compiling an ipa-generated file, do not instrument phases that 00995 // have already been done at ipl time. 00996 if (FILE_INFO_ipa (File_info)) { 00997 if (Instrumentation_Enabled && 00998 Instrumentation_Phase_Num <= PROFILE_PHASE_IPA_CUTOFF) { 00999 Instrumentation_Enabled = FALSE; 01000 Instrumentation_Phase_Num = PROFILE_PHASE_NONE; 01001 } 01002 } 01003 01004 /* initialize the BE symtab. Note that w2cf relies on the BE_ST */ 01005 /* during Phase_Init and Phase_Fini */ 01006 01007 BE_symtab_initialize_be_scopes(); 01008 BE_symtab_alloc_scope_level(GLOBAL_SYMTAB); 01009 SYMTAB_IDX scope_level; 01010 for (scope_level = 0; 01011 scope_level <= GLOBAL_SYMTAB; 01012 ++scope_level) { 01013 // No need to deal with levels that don't have st_tab's. Currently 01014 // this should be only zero. 01015 if (Scope_tab[scope_level].st_tab != NULL) { 01016 Scope_tab[scope_level].st_tab-> 01017 Register(*Be_scope_tab[scope_level].be_st_tab); 01018 } 01019 else { 01020 Is_True(scope_level == 0, 01021 ("Nonexistent st_tab for level %d", scope_level)); 01022 } 01023 } 01024 01025 Phase_Init (); 01026 01027 if (Run_preopt || Run_wopt || Run_lno || Run_Distr_Array || Run_autopar 01028 || Run_cg) { 01029 Set_Error_Descriptor (EP_BE, EDESC_BE); 01030 } 01031 /* For UPC - disable optimizations for the time being */ 01032 if (Compile_Upc) { 01033 Run_lno = 0; 01034 if (Run_w2c) { 01035 //the symbols should already be in the symbol table, need to find them 01036 Find_Upc_Vars(); 01037 } 01038 } 01039 01040 if (Tlog_File) 01041 Print_Tlog_Header(argc, argv); 01042 01043 01044 for (PU_Info *current_pu = pu_tree; 01045 current_pu != NULL; 01046 current_pu = PU_Info_next(current_pu)) { 01047 Preorder_Process_PUs(current_pu); 01048 } 01049 01050 if(Compile_Upc && !Run_w2c) 01051 Upc_Lower_SymbolTable(); 01052 01053 /* Terminate stdout line if showing PUs: */ 01054 if (Show_Progress) { 01055 fprintf (stderr, "\n"); 01056 fflush (stderr); 01057 } 01058 01059 Phase_Fini (); 01060 01061 /* free the BE symtabs. w2cf requires BE_ST in Phase_Fini */ 01062 01063 Is_True(scope_level == GLOBAL_SYMTAB + 1, 01064 ("scope_level must be GLOBAL_SYMTAB + 1, left from earlier loop")); 01065 01066 do { 01067 --scope_level; 01068 // No need to deal with levels that don't have st_tab's. Currently 01069 // this should be only zero. 01070 if (Scope_tab[scope_level].st_tab != NULL) { 01071 Scope_tab[scope_level].st_tab-> 01072 Un_register(*Be_scope_tab[scope_level].be_st_tab); 01073 Be_scope_tab[scope_level].be_st_tab->Clear(); 01074 } 01075 else { 01076 Is_True(scope_level == 0, 01077 ("Nonexistent st_tab for level %d", scope_level)); 01078 } 01079 } while (scope_level != 0); 01080 01081 BE_symtab_free_be_scopes(); 01082 01083 01084 if (need_wopt_output || need_lno_output || need_ipl_output) { 01085 Write_Global_Info (pu_tree); 01086 if (need_ipl_output) 01087 Ipl_Extra_Output (ir_output); 01088 Close_Output_Info (); 01089 } 01090 else if (Emit_Global_Data) { 01091 Write_Global_Info (NULL); /* even if dummy pu, don't write any pu's */ 01092 Close_Output_Info (); 01093 } 01094 01095 /* Print miscellaneous statistics to trace file: */ 01096 Print_Total_Stats (); 01097 if ((Opt_Level > 0 || Run_autopar) 01098 && Max_Src_Olimit > Olimit && !Olimit_opt && Show_OPT_Warnings) { 01099 ErrMsg (EC_File_Olimit_Exceeded, Max_Src_Olimit); 01100 } 01101 01102 Stop_Timer(T_BE_Comp); 01103 Finish_Compilation_Timing ( Tim_File, Src_File_Name ); 01104 01105 MEM_POOL_Pop ( &MEM_src_pool ); 01106 MEM_POOL_Pop ( &MEM_src_nz_pool ); 01107 #ifdef Is_True_On 01108 if (Get_Trace (TKIND_ALLOC, TP_MISC)) { 01109 fprintf (TFile, "\n%s\tMemory allocation information after be\n", DBar); 01110 MEM_Trace (); 01111 } 01112 #endif 01113 01114 /* If we've seen errors, note them and terminate: */ 01115 if ( Get_Error_Count ( &local_ecount, &local_wcount ) ) { 01116 ecount += local_ecount; 01117 } 01118 01119 if ( ecount > 0 ) { 01120 Terminate(Had_Internal_Error() ? RC_INTERNAL_ERROR : RC_NORECOVER_USER_ERROR) ; 01121 } 01122 01123 /* Close and delete files as necessary: */ 01124 Cleanup_Files ( TRUE, FALSE ); 01125 01126 01127 exit ( RC_OKAY ); 01128 /*NOTREACHED*/ 01129 01130 01131 } /* main */ 01132 01133 01134 static BOOL 01135 Has_Extension__1 (char *name, /* The filename to check */ 01136 char *ext) /* The extension to look for */ 01137 { 01138 INT16 nlen = strlen(name); 01139 INT16 elen = strlen(ext); 01140 01141 /* If ext is longer than name, no chance: */ 01142 if ( elen > nlen ) return FALSE; 01143 01144 /* Otherwise compare the tail of name to ext: */ 01145 return ( strcmp ( &name[nlen-elen], ext ) == 0 ); 01146 } /* Has_Extension__1 */ 01147 01148 01149 static char *libpath[3] = 01150 {"LD_LIBRARY_PATH", 01151 "LD_LIBRARYN32_PATH", 01152 "LD_LIBRARY64_PATH" 01153 }; 01154 static const char * const errstring = "%s: can't allocate memory\n"; 01155 01156 void RiceWhirl2f (INT * _argc, char * **_argv) { 01157 char path[PATH_MAX]; 01158 char *p; 01159 char *env; 01160 char * myname; 01161 int argidx, i, len; 01162 char **new_argv; 01163 BOOL dash_fB_option = FALSE; 01164 char *newlibpath[3]; 01165 int argc = *_argc; 01166 char **argv = *_argv; 01167 myname= Last_Pathname_Component (argv[0]); 01168 01169 if (myname && strcmp(myname, "whirl2f90") == 0) { 01170 01171 // set Run_w2f 01172 Run_w2f=1; 01173 strcpy (path, argv[0]); 01174 if (p = strrchr(path, '/')) 01175 p[0] = 0; 01176 else 01177 strcpy (path, "."); 01178 01179 for (i = 0; i<3; i++) 01180 { 01181 len = strlen (path) + 1; 01182 len += strlen (libpath[i]) + 1; /* env. variable name plus '=' */ 01183 01184 env = getenv (libpath[i]); 01185 01186 if (env) { 01187 len += strlen (env) + 1; /* old path plus ':' */ 01188 01189 newlibpath[i] = (char *) malloc (len); 01190 if (newlibpath[i] == 0) { 01191 fprintf (stderr, errstring, argv[0]); 01192 exit(RC_NORECOVER_USER_ERROR); 01193 } 01194 01195 sprintf (newlibpath[i], "%s=%s:%s", libpath[i], env, path); 01196 } else { 01197 newlibpath[i] = (char *) malloc (len); 01198 if (newlibpath[i] == 0) { 01199 fprintf (stderr, errstring, argv[0]); 01200 exit(RC_NORECOVER_USER_ERROR); 01201 } 01202 01203 sprintf (newlibpath[i], "%s=%s", libpath[i], path); 01204 } 01205 } /* For each libpath kind */ 01206 for (i = 0; i<3; i++) 01207 putenv (newlibpath[i]); 01208 // strcat (path, "/whirl2f"); 01209 01210 01211 /* Copy the argument list into a new list of strings, with a spare 01212 * element for a missing -fB option. 01213 */ 01214 new_argv = (char **) malloc((argc+2)*sizeof(char *)); 01215 for (argidx = 0; argidx < argc; argidx++) 01216 { 01217 new_argv[argidx] = (char *) malloc(strlen(argv[argidx]) + 1); 01218 new_argv[argidx] = strcpy(new_argv[argidx], argv[argidx]); 01219 if (new_argv[argidx][0] == '-' && 01220 new_argv[argidx][1] == 'f' && 01221 new_argv[argidx][2] == 'B') 01222 dash_fB_option = TRUE; 01223 } 01224 01225 if (!dash_fB_option) 01226 { 01227 /* Create a "-fB" option, provided the file-argument (only argument 01228 * not preceded by a '-') represents the WHIRL file if suffixed by 01229 * ".B", ".I", ".N" or ".o". 01230 */ 01231 argidx = argc-1; 01232 while (argidx > 0) 01233 { 01234 if (new_argv[argidx][0] != '-' && /* A file argument */ 01235 (Has_Extension__1(new_argv[argidx], ".B") || 01236 Has_Extension__1(new_argv[argidx], ".I") || 01237 Has_Extension__1(new_argv[argidx], ".N") || 01238 Has_Extension__1(new_argv[argidx], ".o"))) 01239 { 01240 /* A file argument representing the WHIRL input file. We need 01241 * to change this around a little bit. Put this filename under 01242 * a "-fB,filename" option and add a new filename with the 01243 * suffix substituted by ".f". 01244 */ 01245 dash_fB_option = TRUE; 01246 new_argv[argc] = (char *) malloc(strlen(new_argv[argidx]) + 5); 01247 (void)strcpy(new_argv[argc], "-fB,"); 01248 (void)strcpy(&new_argv[argc][4], new_argv[argidx]); 01249 argc++; 01250 01251 new_argv[argidx][strlen(new_argv[argidx])-1] = 'f'; 01252 argidx = 1; /* We are done! */ 01253 } 01254 argidx--; 01255 } /*while*/ 01256 } /*if (!dash_fB_option)*/ 01257 new_argv[argc] = NULL; 01258 01259 // change the program name to be whirl2f 01260 new_argv[0][ strlen(new_argv[0])-2 ] = 0; 01261 01262 * _argc = argc; 01263 * _argv = new_argv; 01264 } 01265 } 01266