driver.cxx

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

Generated on Tue Nov 17 05:54:26 2009 for Open64 (mfef90, whirl2f, and IR tools) by  doxygen 1.6.1