Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
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 #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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines