Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
curr.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 <libgen.h>
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 "cgdriver.h"               /* for CG_Init, etc. */
00083 #include "optimizer.h"              /* for alias manager, etc. */
00084 #include "ori.h"                    /* for Olimit_Region_Insertion */
00085 #include "wodriver.h"               /* for wopt_main, etc. */
00086 #include "lnodriver.h"              /* for lno_main, etc. */
00087 #include "ipl_driver.h"             /* for ipl_main. etc. */
00088 #include "w2c_driver.h"             /* for W2C_Process_Command_Line, etc. */
00089 #include "w2f_driver.h"             /* for W2F_Process_Command_Line, etc. */
00090 #include "prp_driver.h"             /* for Prp_Process_Command_Line, etc. */
00091 #include "anl_driver.h"             /* for Anl_Process_Command_Line, etc. */
00092 #include "region_util.h"            /* for Regions_Around_Inner_Loops */
00093 #include "region_main.h"            /* for REGION_* driver specific routines */
00094 #include "cg/cg.h"                  /* for CG PU-level routines */
00095 #include "tracing.h"                /* For the trace routines */
00096 #include "ir_reader.h"              /* For fdump_tree */
00097 #include "dwarf_DST.h"              /* for Orig_PU_Name */
00098 #include "fb_whirl.h"               /* for FEEDBACK */
00099 #include "eh_region.h"              /* for EH_Generate_Range_List, etc. */
00100 #include "vho_lower.h"
00101 #include "iter.h"                   /* PU iterator for loops */
00102 #include "dra_export.h"             /* for DRA routines */
00103 #include "ti_init.h"                /* for targ_info */
00104 #include "opt_alias_interface.h"    /* for Create_Alias_Manager */
00105 #include "omp_lower.h"              /* for OMP pre-lowering interface */
00106 #include "cxx_memory.h"             /* CXX_NEW */
00107 #include "options_stack.h"          /* for Options_Stack */
00108 #include "be_symtab.h"              /* for Be_preg_tab */
00109 #include "prompf.h"                 /* Prompf support */ 
00110 #include "wb_omp.h"                 /* whirl browser for omp prelowerer */
00111 #include "wb_lwr.h"                 /* whirl browser for lowerer */ 
00112 #include "wb_anl.h"                 /* whirl browser for prompf static anal */ 
00113 #include "wn_instrument.h"          /* whirl instrumenter */
00114 #include "mem_ctr.h"
00115 
00116 
00117 #if defined(__CYGWIN__)
00118 # define DSOext ".dll" /* cygwin needs to use dll for DSOs */
00119 #else
00120 # define DSOext ".so"
00121 #endif
00122 
00123 
00124 extern void Initialize_Targ_Info(void);
00125 
00126 #if defined(_GCC_NO_PRAGMAWEAK) || defined(__CYGWIN__)
00127 extern "C" {
00128 INT64       New_Construct_Id(void) { return 0; }
00129 INT64       Get_Next_Construct_Id(void) { return 0; }
00130 }
00131 #endif
00132 
00133 
00134 // symbols defined in cg.so
00135 #if defined(__linux__) || defined(_GCC_NO_PRAGMAWEAK) || defined(__CYGWIN__)
00136 
00137 extern void (*CG_Process_Command_Line_p) (INT, char **, INT, char **);
00138 #define CG_Process_Command_Line (*CG_Process_Command_Line_p)
00139 
00140 extern void (*CG_Init_p) ();
00141 #define CG_Init (*CG_Init_p)
00142 
00143 extern void (*CG_Fini_p) ();
00144 #define CG_Fini (*CG_Fini_p)
00145 
00146 extern void (*CG_PU_Initialize_p) (WN*);
00147 #define CG_PU_Initialize (*CG_PU_Initialize_p)
00148 
00149 extern void (*CG_PU_Finalize_p) ();
00150 #define CG_PU_Finalize (*CG_PU_Finalize_p)
00151 
00152 extern WN* (*CG_Generate_Code_p) (WN*, ALIAS_MANAGER*, DST_IDX, BOOL);
00153 #define CG_Generate_Code (*CG_Generate_Code_p)
00154 
00155 extern void (*EH_Generate_Range_List_p) (WN *);
00156 #define EH_Generate_Range_List (*EH_Generate_Range_List_p)
00157 
00158 #else
00159 
00160 #pragma weak CG_Process_Command_Line
00161 #pragma weak CG_Init
00162 #pragma weak CG_Fini
00163 #pragma weak CG_PU_Finalize
00164 #pragma weak CG_PU_Initialize
00165 #pragma weak CG_Generate_Code
00166 #pragma weak EH_Generate_Range_List
00167 
00168 #endif // __linux__
00169 
00170 
00171 // symbols defined in wopt.so
00172 #if defined(__linux__) || defined(_GCC_NO_PRAGMAWEAK) || defined(__CYGWIN__)
00173 
00174 extern void (*wopt_main_p) (INT argc, char **argv, INT, char **);
00175 #define wopt_main (*wopt_main_p)
00176 
00177 extern void (*Wopt_Init_p) ();
00178 #define Wopt_Init (*Wopt_Init_p)
00179 
00180 extern void (*Wopt_Fini_p) ();
00181 #define Wopt_Fini (*Wopt_Fini_p)
00182 
00183 extern WN* (*Perform_Preopt_Optimization_p) (WN *, WN *);
00184 #define Perform_Preopt_Optimization (*Perform_Preopt_Optimization_p)
00185 
00186 extern WN* (*Perform_Global_Optimization_p) (WN *, WN *, ALIAS_MANAGER *);
00187 #define Perform_Global_Optimization (*Perform_Global_Optimization_p)
00188 
00189 extern WN* (*Pre_Optimizer_p) (INT32, WN*, DU_MANAGER*, ALIAS_MANAGER*);
00190 #define Pre_Optimizer (*Pre_Optimizer_p)
00191 
00192 extern DU_MANAGER* (*Create_Du_Manager_p) (MEM_POOL *);
00193 #define Create_Du_Manager (*Create_Du_Manager_p)
00194 
00195 extern void (*Delete_Du_Manager_p) (DU_MANAGER *, MEM_POOL *);
00196 #define Delete_Du_Manager (*Delete_Du_Manager_p)
00197 
00198 extern BOOL (*Verify_alias_p) (ALIAS_MANAGER *, WN *);
00199 #define Verify_alias (*Verify_alias_p)
00200 
00201 #else
00202 
00203 #pragma weak wopt_main
00204 #pragma weak Wopt_Init
00205 #pragma weak Wopt_Fini
00206 #pragma weak Perform_Global_Optimization
00207 #pragma weak Perform_Preopt_Optimization
00208 #pragma weak Pre_Optimizer
00209 #pragma weak Create_Du_Manager
00210 #pragma weak Delete_Du_Manager
00211 #pragma weak Verify_alias
00212 
00213 #endif // __linux__
00214 
00215 
00216 // symbols defined in lno.so
00217 #if defined(__linux__) || defined(_GCC_NO_PRAGMAWEAK) || defined(__CYGWIN__)
00218 
00219 extern void (*lno_main_p) (INT, char**, INT, char**);
00220 #define lno_main (*lno_main_p)
00221 
00222 extern void (*Lno_Init_p) ();
00223 #define Lno_Init (*Lno_Init_p)
00224 
00225 extern void (*Lno_Fini_p) ();
00226 #define Lno_Fini (*Lno_Fini_p)
00227 
00228 extern WN* (*Perform_Loop_Nest_Optimization_p) (PU_Info*, WN*, WN*, BOOL);
00229 #define Perform_Loop_Nest_Optimization (*Perform_Loop_Nest_Optimization_p)
00230 
00231 #else 
00232 
00233 #pragma weak lno_main
00234 #pragma weak Lno_Init
00235 #pragma weak Lno_Fini
00236 #pragma weak Perform_Loop_Nest_Optimization
00237 
00238 #endif // __linux__
00239 
00240 
00241 // symbols defined in ipl.so
00242 #if defined(__linux__) || defined(_GCC_NO_PRAGMAWEAK) || defined(__CYGWIN__)
00243 
00244 extern void (*Ipl_Extra_Output_p) (Output_File *);
00245 #define Ipl_Extra_Output (*Ipl_Extra_Output_p)
00246 
00247 extern void (*Ipl_Init_p) ();
00248 #define Ipl_Init (*Ipl_Init_p)
00249 
00250 extern void (*Ipl_Fini_p) ();
00251 #define Ipl_Fini (*Ipl_Fini_p)
00252 
00253 extern void (*ipl_main_p) (INT, char **);
00254 #define ipl_main (*ipl_main_p)
00255 
00256 extern void (*Perform_Procedure_Summary_Phase_p) (WN*, DU_MANAGER*,
00257                                                   ALIAS_MANAGER*, void*);
00258 #define Perform_Procedure_Summary_Phase (*Perform_Procedure_Summary_Phase_p)
00259 
00260 #else
00261 
00262 #pragma weak ipl_main
00263 #pragma weak Ipl_Init
00264 #pragma weak Ipl_Fini
00265 #pragma weak Ipl_Extra_Output
00266 #pragma weak Perform_Procedure_Summary_Phase
00267 
00268 #endif // __linux__
00269 
00270 
00271 #include "w2c_weak.h"
00272 #include "w2f_weak.h"
00273 
00274 
00275 #if defined(_GCC_NO_PRAGMAWEAK) || defined(__CYGWIN__)
00276 void        Anl_Process_Command_Line (INT phase_argc, char *phase_argv[],
00277                                       INT argc, char *argv[]) { }
00278 BOOL        Anl_Needs_Whirl2c(void) { return false; }
00279 BOOL        Anl_Needs_Whirl2f(void) { return false; }
00280 void        Anl_Init(void) { }
00281 WN_MAP      Anl_Init_Map(MEM_POOL *id_map_pool) { return NULL; }
00282 void        Anl_Static_Analysis(WN *pu, WN_MAP id_map) { }
00283 const char *Anl_File_Path(void)        { return NULL; }
00284 void        Anl_Fini(void)   { }
00285 void        Anl_Cleanup(void){ }
00286 void        Prp_Process_Command_Line (INT phase_argc, char *phase_argv[],
00287                                INT argc, char *argv[]) { }
00288 BOOL        Prp_Needs_Whirl2c(void) { return false; }
00289 BOOL        Prp_Needs_Whirl2f(void) { return false; }
00290 void        Prp_Init(void)          { }
00291 void        Prp_Instrument_And_EmitSrc(WN *pu) { }
00292 void        Prp_Fini(void) { } 
00293 void        Prompf_Emit_Whirl_to_Source(PU_Info* current_pu,
00294                                         WN* func_nd) { }
00295 
00296 #else
00297 
00298 #pragma weak Prp_Process_Command_Line
00299 #pragma weak Prp_Needs_Whirl2c
00300 #pragma weak Prp_Needs_Whirl2f
00301 #pragma weak Prp_Init
00302 #pragma weak Prp_Instrument_And_EmitSrc
00303 #pragma weak Prp_Fini
00304 #pragma weak Anl_Cleanup
00305 #pragma weak Anl_Process_Command_Line
00306 #pragma weak Anl_Needs_Whirl2c
00307 #pragma weak Anl_Needs_Whirl2f
00308 #pragma weak Anl_Init
00309 #pragma weak Anl_Init_Map
00310 #pragma weak Anl_Static_Analysis
00311 #pragma weak Anl_Fini
00312 
00313 #endif
00314 
00315 
00316 /* Solaris CC porting
00317  * Solaris CC #pragma weak can be either followed by one mangled name in
00318  * string form, or followed by two mangled names. A better way is to 
00319  * define an Asserta and let these weak functions to equal to Asserta
00320  */
00321 #if !defined(__GNUC__) && defined(_SOLARIS_SOLARIS)
00322 
00323 #pragma weak "__1cbBPrompf_Emit_Whirl_to_Source6FpnHpu_info_pnCWN__v_"
00324 
00325 #elif !defined(__GNUC__)
00326 #pragma weak Prompf_Emit_Whirl_to_Source__GP7pu_infoP2WN
00327 
00328 #else
00329 #pragma weak Prompf_Emit_Whirl_to_Source__FP7pu_infoP2WN
00330 #endif
00331 
00332 extern void Prompf_Emit_Whirl_to_Source(PU_Info* current_pu, WN* func_nd);
00333 
00334 
00335 static INT ecount = 0;
00336 static BOOL need_wopt_output = FALSE;
00337 static BOOL need_lno_output = FALSE;
00338 static BOOL need_ipl_output = FALSE;
00339 static Output_File *ir_output = 0;
00340 
00341 // options stack for PU and region level pragmas
00342 static OPTIONS_STACK *Options_Stack;
00343 
00344 static BOOL reset_opt_level = FALSE;
00345 static struct ALIAS_MANAGER *alias_mgr = NULL;
00346 
00347 static BOOL Run_Distr_Array = FALSE;
00348 BOOL Run_MemCtr = FALSE;
00349 
00350 static BOOL Saved_run_prompf = FALSE; /* TODO: Remove when uses are removed */
00351 static BOOL Saved_run_w2c = FALSE;        /* TODO: Remove */
00352 static BOOL Saved_run_w2f = FALSE;        /* TODO: Remove */
00353 static BOOL Saved_run_w2fc_early = FALSE; /* TODO: Remove */
00354 
00355 extern WN_MAP Prompf_Id_Map; /* Maps WN constructs to unique identifiers */
00356 
00357 /* Keep track of which optional components are loaded, where we need
00358  * to do so.
00359  */
00360 static BOOL   wopt_loaded = FALSE;
00361 extern BOOL   Prompf_anl_loaded; /* Defined in cleanup.c */
00362 extern BOOL   Purple_loaded;     /* Defined in cleanup.c */
00363 extern BOOL   Whirl2f_loaded;    /* Defined in cleanup.c */
00364 extern BOOL   Whirl2c_loaded;    /* Defined in cleanup.c */
00365 
00366 extern void *Current_Dep_Graph;
00367 FILE *DFile = stderr;
00368 
00369 static void
00370 load_components (INT argc, char **argv)
00371 {
00372     INT phase_argc;
00373     char **phase_argv;
00374 
00375     if (Run_cg || Run_lno || Run_autopar) {
00376       // initialize target-info before cg or lno
00377       Initialize_Targ_Info();
00378     }
00379 
00380     if (!(Run_lno || Run_wopt || Run_preopt || Run_cg || 
00381           Run_prompf || Run_purple || Run_w2c || Run_w2f 
00382           || Run_w2fc_early || Run_ipl))
00383       Run_cg = TRUE;                /* if nothing is set, run CG */
00384 
00385     if (Run_ipl) {
00386       Run_lno = Run_wopt = Run_cg = Run_w2fc_early
00387         = Run_prompf = Run_purple = Run_w2c = Run_w2f = FALSE;
00388     }
00389 
00390     if (Run_cg) {
00391       Get_Phase_Args (PHASE_CG, &phase_argc, &phase_argv);
00392       load_so ("cg" DSOext, CG_Path, Show_Progress);
00393       CG_Process_Command_Line (phase_argc, phase_argv, argc, argv);
00394     }
00395 
00396     if (Run_wopt || Run_preopt || Run_lno || Run_autopar) {
00397       Get_Phase_Args (PHASE_WOPT, &phase_argc, &phase_argv);
00398       load_so ("wopt" DSOext, WOPT_Path, Show_Progress);
00399       wopt_main (phase_argc, phase_argv, argc, argv);
00400       wopt_loaded = TRUE;
00401     }
00402 
00403     if (Run_ipl) {
00404       Get_Phase_Args (PHASE_IPL, &phase_argc, &phase_argv);
00405       load_so ("ipl" DSOext, Ipl_Path, Show_Progress);
00406       ipl_main (phase_argc, phase_argv);
00407       Set_Error_Descriptor (EP_BE, EDESC_BE);
00408     }
00409 
00410     if (Run_lno || Run_autopar) {
00411       Get_Phase_Args (PHASE_LNO, &phase_argc, &phase_argv);
00412       load_so ("lno" DSOext, LNO_Path, Show_Progress);
00413       lno_main (phase_argc, phase_argv, argc, argv);
00414 
00415       // load in ipl.so if we need to perform automatic
00416       // parallelization and interprocedural analysis has
00417       // been performed
00418       if (Run_autopar && LNO_IPA_Enabled) {
00419           load_so("ipl" DSOext, Ipl_Path, Show_Progress);
00420       }
00421   }
00422 
00423     if (Run_prompf || Run_w2fc_early) {
00424       Get_Phase_Args (PHASE_PROMPF, &phase_argc, &phase_argv);
00425       load_so("prompf_anl" DSOext, Prompf_Anl_Path, Show_Progress);
00426       Prompf_anl_loaded = TRUE;
00427       Anl_Process_Command_Line(phase_argc, phase_argv, argc, argv);
00428     }
00429 
00430     if (Run_purple) {
00431       Get_Phase_Args (PHASE_PURPLE, &phase_argc, &phase_argv);
00432       load_so("purple" DSOext, Purple_Path, Show_Progress);
00433       Purple_loaded = TRUE;
00434       Prp_Process_Command_Line(phase_argc, phase_argv, argc, argv);
00435     }
00436 
00437     if (Run_w2c || 
00438         (Run_prompf && Anl_Needs_Whirl2c()) ||
00439         (Run_purple && Prp_Needs_Whirl2c()))
00440     {
00441       Get_Phase_Args (PHASE_W2C, &phase_argc, &phase_argv);
00442       load_so("whirl2c" DSOext, W2C_Path, Show_Progress);
00443       Whirl2c_loaded = TRUE;
00444       if (Run_prompf)
00445         W2C_Set_Prompf_Emission(&Prompf_Id_Map);
00446       W2C_Process_Command_Line(phase_argc, phase_argv, argc, argv);
00447     }
00448 
00449     if (Run_w2f || 
00450         (Run_prompf && Anl_Needs_Whirl2f()) ||
00451         (Run_purple && Prp_Needs_Whirl2f()))
00452     {
00453       Get_Phase_Args (PHASE_W2F, &phase_argc, &phase_argv);
00454       load_so("whirl2f" DSOext, W2F_Path, Show_Progress);
00455       Whirl2f_loaded = TRUE;
00456       if (Run_prompf)
00457         W2F_Set_Prompf_Emission(&Prompf_Id_Map);
00458 
00459       W2F_Process_Command_Line(phase_argc, phase_argv, argc, argv);
00460     }
00461 } /* load_components */
00462 
00463 
00464 /* phase-specific initializations that need to be done after reading
00465  * in the global symbol tables.
00466  */
00467 static void
00468 Phase_Init (void)
00469 {
00470     char *output_file_name = Obj_File_Name;
00471 
00472     if (Run_Distr_Array      && 
00473         (Run_w2c || Run_w2f) &&
00474         !Run_lno             &&
00475         !Run_wopt            &&
00476         !Run_cg)
00477     {
00478        /* A special case, where it looks as though we only wish to
00479         * run some early phases and then put out the flist or clist.
00480         * Disable the turning on of subsequent phases due to the
00481         * Run_Distr_Array flag.
00482         */
00483        Run_Distr_Array = FALSE;
00484     }
00485     if ( LNO_Run_Lego_Set && ( LNO_Run_Lego == FALSE ) )
00486       Run_Distr_Array = FALSE;
00487 
00488     if (Run_cg)
00489         CG_Init ();
00490     if (Run_wopt || Run_preopt)
00491         Wopt_Init ();
00492     if (Run_ipl)
00493         Ipl_Init ();
00494     if (Run_lno || Run_Distr_Array || Run_autopar)
00495         Lno_Init ();
00496     if (Run_purple)
00497         Prp_Init();
00498     if (Run_w2c || (Run_prompf && Anl_Needs_Whirl2c()))
00499         W2C_Outfile_Init (TRUE/*emit_global_decls*/);
00500     if (Run_w2f || (Run_prompf && Anl_Needs_Whirl2f()))
00501         W2F_Outfile_Init ();
00502     if (Run_prompf) 
00503         Anl_Init (); 
00504         /* Must be done after w2c and w2f */
00505     if ((Run_lno || Run_preopt) && !Run_cg && !Run_wopt)
00506         need_lno_output = TRUE;
00507     if (Run_wopt && !Run_cg)
00508         need_wopt_output = TRUE;
00509 
00510     if (Run_ipl) {
00511         need_ipl_output = TRUE;
00512         need_lno_output = need_wopt_output = FALSE;
00513     }
00514 
00515     if (output_file_name == 0) {
00516         if (Src_File_Name)
00517             output_file_name = Last_Pathname_Component (Src_File_Name);
00518         else
00519             output_file_name = Irb_File_Name;
00520     }
00521 
00522     if (need_lno_output) {
00523         Write_BE_Maps = TRUE;
00524         ir_output = Open_Output_Info(New_Extension(output_file_name,".N"));
00525     }
00526     if (need_wopt_output) {
00527         Write_ALIAS_CLASS_Map = TRUE;
00528         Write_BE_Maps = TRUE;
00529         ir_output = Open_Output_Info(New_Extension(output_file_name,".O"));
00530     }
00531     if (need_ipl_output) {
00532         Write_BE_Maps = FALSE;
00533         ir_output = Open_Output_Info (Obj_File_Name ?
00534                                       Obj_File_Name :
00535                                       New_Extension(output_file_name, ".o"));
00536     }
00537     if (Emit_Global_Data) {
00538         Write_BE_Maps = FALSE;
00539         ir_output = Open_Output_Info (Global_File_Name);
00540     }
00541         
00542     if (Run_wopt) {
00543       if (Language != LANG_KR_C) {
00544         Pad_Global_Arrays();
00545       }
00546     }
00547     if ((Run_cg || Run_wopt) && !Read_Global_Data)
00548         Allocate_File_Statics();        /* allocate globals */
00549 
00550 } /* Phase_Init */
00551 
00552 
00553 static void
00554 Phase_Fini (void)
00555 {
00556     CURRENT_SYMTAB = GLOBAL_SYMTAB;
00557 
00558     /* Always finish prompf analysis file, purple, w2c and w2f first */
00559     if (Run_prompf)
00560         Anl_Fini();
00561     if (Run_purple)
00562         Prp_Fini();
00563     if (Run_w2c || (Run_prompf && Anl_Needs_Whirl2c()))
00564         W2C_Outfile_Fini (TRUE/*emit_global_decls*/);
00565     if (Run_w2f || (Run_prompf && Anl_Needs_Whirl2f()))
00566         W2F_Outfile_Fini ();
00567 
00568     if (Run_Dsm_Cloner || Run_Dsm_Common_Check)
00569       DRA_Finalize ();
00570 
00571     if (Run_lno || Run_Distr_Array || Run_autopar)
00572         Lno_Fini ();
00573     if (Run_ipl)
00574         Ipl_Fini ();
00575     if (Run_wopt || Run_preopt)
00576         Wopt_Fini ();
00577     if (Run_cg)
00578         CG_Fini ();
00579 
00580     Verify_SYMTAB (CURRENT_SYMTAB); /* Verifies global SYmtab */
00581 } /* Phase_Fini */
00582 
00583 /* static */ char *
00584 Get_Orig_PU_Name (PU_Info * current_pu)
00585 {
00586     DST_IDX dst;
00587     DST_INFO *info;
00588     DST_SUBPROGRAM *PU_attr;
00589 
00590     dst = PU_Info_pu_dst(current_pu);
00591 
00592     if (DST_IS_NULL (dst)) {
00593        return ST_name(PU_Info_proc_sym(current_pu));
00594     }
00595 
00596     info = DST_INFO_IDX_TO_PTR (dst);
00597 
00598     if ( (DST_INFO_tag(info) != DW_TAG_subprogram)
00599         || DST_IS_declaration(DST_INFO_flag(info)) )
00600     {
00601         return ST_name(PU_Info_proc_sym(current_pu));
00602     }
00603     PU_attr = DST_ATTR_IDX_TO_PTR(DST_INFO_attributes(info), DST_SUBPROGRAM);
00604     if (PU_attr->def.name.byte_idx < 0) {
00605       return NULL;
00606       /* Why not the following line instead? -- RK 960808
00607        * return ST_name(PU_Info_proc_sym(current_pu));
00608        */
00609     }
00610     return DST_STR_IDX_TO_PTR(DST_SUBPROGRAM_def_name(PU_attr));
00611 }
00612 
00613 static void
00614 Save_Cur_PU_Name (char *name, INT rid_id)
00615 {
00616     if ( Cur_PU_Name == NULL ) {
00617         /* ST_name will return a pointer into the symbol table, which is
00618          * mmap-ed. This causes a problem in the error message routines
00619          * when an unexpected signal occurs, because as part of the cleanup
00620          * files are closed. To fix the problem we just allocate some
00621          * memory and make a copy.
00622          * Allocate 8 extra bytes to leave room for RGN suffix.
00623          */
00624         Cur_PU_Name = TYPE_MEM_POOL_ALLOC_N(char, &MEM_pu_nz_pool, 
00625                 strlen(name) + 8);
00626         Cur_PU_Name = strcpy(Cur_PU_Name, name);
00627     }
00628     if (rid_id != 0) {
00629         /* add RGN suffix */
00630         sprintf(Cur_PU_Name,"%s.RGN%03d", name, rid_id);
00631     }
00632     else if (strlen(name) != strlen(Cur_PU_Name)) {
00633         /* clear RGN suffix */
00634         Cur_PU_Name = strcpy(Cur_PU_Name, name);
00635     }
00636 }
00637 
00638 
00639 //  Adjust/Lower optimization level based on
00640 //   1. size of PU and Olimit
00641 //   2. existence of non-ANSI setjmp calls
00642 //
00643 static WN *
00644 Adjust_Opt_Level (PU_Info* current_pu, WN *pu, char *pu_name)
00645 {
00646     INT new_opt_level = 0;
00647     COMPUTE_PU_OLIMIT;
00648 
00649     if (Get_Trace(TKIND_INFO, TINFO_STATS)) {
00650         /* Print Olimit stats to trace file: */
00651         INT PU_Var_Cnt = ST_Table_Size (CURRENT_SYMTAB) +
00652             PREG_Table_Size (CURRENT_SYMTAB); 
00653         fprintf (TFile, "PU_Olimit for %s is %d (bbs=%d,stms=%d,vars=%d)\n", 
00654                 pu_name, PU_Olimit, PU_WN_BB_Cnt, PU_WN_Stmt_Cnt, PU_Var_Cnt);
00655     }
00656 
00657     if ((Opt_Level > 0 || Run_autopar) && PU_Olimit > Olimit && !Olimit_opt) {
00658         if (Show_OPT_Warnings)
00659           ErrMsg (EC_Olimit_Exceeded, pu_name, PU_Olimit);
00660         reset_opt_level = TRUE;
00661     }
00662     if (((Opt_Level > 0 || Run_autopar) || Olimit_opt)
00663       && Query_Skiplist ( Optimization_Skip_List, Current_PU_Count() ) )
00664     {
00665         if (Show_OPT_Warnings)
00666           ErrMsg (EC_Not_Optimized, pu_name, Current_PU_Count() );
00667         reset_opt_level = TRUE;
00668     } 
00669     if (/* !LANG_Ansi_Setjmp_On && */ 
00670       /* 1. Cannot check LANG_Ansi_Setjmp_On because IPA does not pass -LANG group.
00671          2. The ST_pu_calls_setjmp is not set unless LANG_Ansi_Setjmp_On = false */
00672         PU_calls_setjmp (Get_Current_PU ())) {
00673       reset_opt_level = TRUE;
00674       new_opt_level = 1;
00675       ErrMsg (EC_Not_Ansi_Setjmp, pu_name, Current_PU_Count(), new_opt_level );
00676     } 
00677     if (reset_opt_level) {
00678         Opt_Level = new_opt_level;
00679         Run_lno = Run_preopt = Run_wopt = Run_autopar = FALSE;
00680         alias_mgr = NULL;
00681         Olimit_opt = FALSE;
00682         if (Run_prompf) 
00683           Prompf_Emit_Whirl_to_Source(current_pu, pu);
00684     }
00685 
00686     if ((PU_Olimit > Olimit) && Olimit_opt) {
00687       /* split into regions (ORI) */
00688       pu = Olimit_Region_Insertion (pu, Olimit);
00689       /* 457243, for 7.2 throttle back LNO when Olimit is reached.
00690        * For 7.2 LNO runs on the PU, for 7.3 it will run on regions.
00691        * options: -LNO:ou=1:fusion=0
00692        * variables: UINT32 Outer_unroll = 1, UINT32 Fusion = 0
00693        * common/com/config_lno.h
00694        */
00695       if (Run_lno || Run_Distr_Array || Run_preopt || Run_autopar) {
00696         LNO_Outer_Unroll = 1;
00697         LNO_Fusion = 0;
00698         if (Show_OPT_Warnings)
00699           ErrMsg(EC_LNO_Backoff, pu_name, LNO_Outer_Unroll, LNO_Fusion);
00700       }
00701     }
00702 
00703     return pu;
00704 } /* Adjust_Opt_Level */
00705 
00706 static void
00707 Ipl_Processing (PU_Info *current_pu, WN *pu)
00708 {
00709     struct DU_MANAGER *du_mgr = NULL;
00710     struct ALIAS_MANAGER *al_mgr = NULL;
00711 
00712     MEM_POOL_Push (&MEM_local_pool);
00713 
00714     PU_adjust_addr_flags(Get_Current_PU_ST(), pu);
00715 
00716     if (Run_preopt) {
00717         du_mgr = Create_Du_Manager(MEM_pu_nz_pool_ptr);
00718         al_mgr = Create_Alias_Manager(MEM_pu_nz_pool_ptr);
00719         pu = Pre_Optimizer(PREOPT_IPA0_PHASE, pu, du_mgr, al_mgr);
00720 #ifdef Is_True_On
00721         if (Get_Trace (TKIND_ALLOC, TP_IPA)) {
00722             fprintf (TFile, "\n%s%s\tMemory allocation information after"
00723                      " IPA local pre_opt\n%s%s\n", DBar, DBar, DBar, DBar);
00724             MEM_Trace ();
00725         }
00726 #endif
00727         Delete_Alias_Manager (al_mgr, MEM_pu_nz_pool_ptr);
00728         Delete_Du_Manager (du_mgr, MEM_pu_nz_pool_ptr);
00729     } else {
00730         Set_Error_Phase ( "IPA Summary" );
00731         Perform_Procedure_Summary_Phase (pu, du_mgr, al_mgr, 0);
00732     }
00733 
00734     /* Write out the current proc */
00735     Set_PU_Info_tree_ptr(current_pu, pu);
00736 
00737     Write_PU_Info (current_pu);
00738 
00739     MEM_POOL_Pop (&MEM_local_pool);
00740     
00741 } /* Ipl_Processing */
00742 
00743 /*====================================================================*/
00744 /* Compilation time loop: LNO                                         */
00745 /*====================================================================*/
00746 static WN *
00747 LNO_Processing (PU_Info *current_pu, WN *pu)
00748 {
00749   REGION_CS_ITER rgn_iter;
00750 
00751   REGION_CS_ITER_init(&rgn_iter, pu);
00752   /* PV 457243 for Mongoose 7.2 do just the PU (RID_TYPE_func_entry),
00753      for Mongoose 7.3 use: RID_TYPE_olimit | RID_TYPE_pragma
00754      These keeps regions out of LNO for 7.2 */
00755   for (REGION_CS_NoEarlierSub_First(&rgn_iter, pu, RID_TYPE_func_entry);
00756        REGION_CS_NoEarlierSub_While(&rgn_iter);
00757        REGION_CS_NoEarlierSub_Next(&rgn_iter)) {
00758 
00759     WN *rwn;
00760 
00761     rwn = REGION_remove_and_mark(pu, &rgn_iter);
00762     Is_True(rwn != NULL,
00763             ("BE driver, IR inconsistency, LNO loop"));
00764     if (Get_Trace(TP_REGION,TT_REGION_ALL)) {
00765       fprintf(TFile,"===== BE driver, LNO loop: %s %d, stacked=%d\n",
00766               REGION_CS_ITER_is_pu(&rgn_iter) ? "PU" : "RGN",
00767               RID_id(REGION_get_rid(rwn)),
00768               !REGION_CS_ITER_is_not_stacked(&rgn_iter));
00769       RID_WN_Tree_Print(TFile, rwn);
00770     }
00771 
00772     /* Don't (re-)run LNO or preopt on nested mp PU's */
00773     /* unless early mp processing was requested.  In which case */
00774     /* LNO and preopt haven't been run on the nexted mp PU's yet. */
00775     BOOL is_mp = PU_mp (Get_Current_PU ());
00776     BOOL needs_lno = PU_mp_needs_lno (Get_Current_PU ());
00777 
00778     if (!is_mp || Early_MP_Processing) {
00779       if (Run_lno || Run_autopar || (Run_Distr_Array && needs_lno)) {
00780 
00781         if (Early_MP_Processing && is_mp) {
00782           Free_Dep_Graph(); 
00783           Current_Dep_Graph = PU_Info_depgraph_ptr(Current_PU_Info);
00784         }
00785         rwn = Perform_Loop_Nest_Optimization(current_pu, pu, rwn, 
00786           TRUE /*can use alloca*/);
00787         Set_PU_Info_depgraph_ptr(Current_PU_Info,Current_Dep_Graph);
00788         if (Current_Dep_Graph) {
00789           Set_PU_Info_state(Current_PU_Info,WT_DEPGRAPH,Subsect_InMem);
00790         } else {
00791           Set_PU_Info_state(Current_PU_Info,WT_DEPGRAPH,Subsect_Missing);
00792         }
00793 
00794         Check_for_IR_Dump(TP_LNOPT, rwn, "LNO");
00795         if (Get_Trace(TP_REGION,TT_REGION_ALL)) {
00796           fprintf(TFile,"===== After LNO, %s %d, stacked=%d\n",
00797                   REGION_CS_ITER_is_pu(&rgn_iter) ? "PU" : "RGN",
00798                   RID_id(REGION_get_rid(rwn)),
00799                   !REGION_CS_ITER_is_not_stacked(&rgn_iter));
00800           RID_WN_Tree_Print(TFile, rwn);
00801           fdump_tree(TFile, rwn);
00802           RID_set_print(TFile,REGION_get_rid(rwn));
00803         }
00804       } else if (Run_preopt) {
00805         rwn = Perform_Preopt_Optimization(pu, rwn);
00806         Check_for_IR_Dump(TP_GLOBOPT, rwn, "PREOPT");
00807         if (Get_Trace(TP_REGION,TT_REGION_ALL)) {
00808           fprintf(TFile,"===== After PREOPT (:p), %s %d, stacked=%d\n",
00809                   REGION_CS_ITER_is_pu(&rgn_iter) ? "PU" : "RGN",
00810                   RID_id(REGION_get_rid(rwn)),
00811                   !REGION_CS_ITER_is_not_stacked(&rgn_iter));
00812           RID_WN_Tree_Print(TFile, rwn);
00813           fdump_tree(TFile, rwn);
00814           RID_set_print(TFile,REGION_get_rid(rwn));
00815         }
00816       }
00817     } else {
00818       Free_Dep_Graph(); 
00819       Current_Dep_Graph = PU_Info_depgraph_ptr(Current_PU_Info);
00820     }
00821 
00822     if (REGION_CS_ITER_is_not_stacked(&rgn_iter)) /* this is tricky */
00823       pu = rwn;
00824     REGION_replace_from_mark(rwn, &rgn_iter);
00825 
00826     if (Get_Trace(TP_REGION,TT_REGION_ALL)) {
00827       fprintf(TFile,"------------ bottom of LNO loop: -----------\n");
00828       REGION_consistency_check(pu);
00829       RID_WN_Tree_Print(TFile,pu);
00830       if (Run_cg)
00831         fdump_region_tree(TFile,pu);
00832       else
00833         fdump_tree(TFile,pu);
00834       fprintf(TFile,"--------------------------------------------\n");
00835     }
00836   } /* end of compilation time region loop */
00837 
00838   return pu;
00839 } /* LNO_Processing */
00840 
00841 
00842 /* Misc. processing after LNO is done, PU exists as a whole during this
00843    procedure */
00844 static void
00845 Post_LNO_Processing (PU_Info *current_pu, WN *pu)
00846 {
00847     BOOL is_user_visible_pu = (CURRENT_SYMTAB == GLOBAL_SYMTAB + 1) || 
00848                               ((Language == LANG_F90) &&
00849                                (CURRENT_SYMTAB == GLOBAL_SYMTAB + 2) &&
00850                                (!Is_Set_PU_Info_flags(current_pu, PU_IS_COMPILER_GENERATED))) ;
00851     
00852     /* Only run w2c and w2f on top-level PUs, unless otherwise requested.
00853      */
00854     if (Run_w2c && !Run_w2fc_early && !Run_prompf) {
00855         if (W2C_Should_Emit_Nested_PUs() || is_user_visible_pu) {
00856             if (Cur_PU_Feedback)
00857                 W2C_Set_Frequency_Map(WN_MAP_FEEDBACK);
00858             W2C_Outfile_Translate_Pu(pu, TRUE/*emit_global_decls*/);
00859         }
00860     }
00861     if (Run_w2f && !Run_w2fc_early && !Run_prompf) {
00862         if (W2F_Should_Emit_Nested_PUs() || is_user_visible_pu) {
00863             if (Cur_PU_Feedback)
00864                 W2F_Set_Frequency_Map(WN_MAP_FEEDBACK);
00865             W2F_Outfile_Translate_Pu(pu);
00866         }
00867     }
00868 
00869     /* only write .N file for PU, no need to replace region because
00870        REGION_remove_and_mark does nothing for pu (rwn is the pu) */
00871     if (need_lno_output) {
00872         Set_PU_Info_tree_ptr(current_pu, pu);
00873         Write_PU_Info(current_pu);
00874         Verify_SYMTAB (CURRENT_SYMTAB);
00875     }
00876 
00877 } /* Post_LNO_Processing */
00878 
00879 static WN *
00880 WOPT_Processing (PU_Info *current_pu, WN *pu, REGION_CS_ITER *rgn_iter,
00881                  WN *rwn)
00882 {
00883     rwn = Perform_Global_Optimization (pu, rwn, alias_mgr);
00884     Check_for_IR_Dump(TP_GLOBOPT, rwn, "WOPT");
00885     if (Get_Trace(TP_REGION,TT_REGION_ALL)) {
00886       fprintf(TFile, "===== driver, after Perform_Global_Optimization");
00887       fprintf(TFile," RGN %d =====\n", RID_id(REGION_get_rid(rwn)));
00888       RID_WN_Tree_Print(TFile,pu);
00889       fdump_tree(TFile,rwn);
00890       fprintf(TFile,"===== driver ---------------------\n");
00891       fprintf(TFile,"#### Verify_alias, after mainopt, RGN %d\n",
00892               RID_id(REGION_get_rid(rwn)));
00893       Verify_alias(alias_mgr, rwn);
00894       if (Run_cg) /* cg has to be loaded to run this routine */
00895         fdump_region_tree(TFile,rwn);
00896       fprintf(TFile,"#### Verify_alias, done\n");
00897     }
00898 
00899     return rwn;
00900 } /* WOPT_Processing */
00901 
00902 // Performance region loop WOPT-CG
00903 static WN *
00904 Do_WOPT_and_CG_with_Regions (PU_Info *current_pu, WN *pu)
00905 {
00906     REGION_CS_ITER rgn_iter;
00907     BOOL Run_region_bounds;
00908     BOOL cg_one_time = TRUE;
00909 
00910     /* look over whole PU and set up stack model */
00911     Initialize_Stack_Frame (pu);        
00912 
00913     // decide whether the PU has regions that need bounds in it
00914     { RID *rid = REGION_get_rid(pu);
00915       Is_True(rid != NULL && RID_TYPE_func_entry(rid) && RID_id(rid) == 0,
00916               ("Do_WOPT_and_CG_with_Regions, RID is incorrect"));
00917       Run_region_bounds = RID_contains_bounds(rid);
00918       Is_Trace(Get_Trace(TP_REGION, TT_REGION_CG_DEBUG) ||
00919                Get_Trace(TP_REGION, TT_REGION_BOUND_DEBUG),
00920                (TFile,"Driver, RID_contains_bounds(%s) = %c\n",
00921                 ST_name(PU_Info_proc_sym(current_pu)),
00922                 Run_region_bounds ? 'T' : 'F'));
00923     }
00924 
00925     // One alias_mgr for all regions (both cg and wopt need it).
00926     // this is the alias manager for all region instances of
00927     // MainOpt and CG. Preopt uses it's own local alias manager,
00928     // one for each region. Deleted by Post_Process_PU.
00929     if ((Run_wopt || Run_region_bounds) && alias_mgr == 0)
00930       alias_mgr = Create_Alias_Manager(MEM_pu_nz_pool_ptr);
00931 
00932     // Create the region boundary sets, be/region/region_bounds.cxx
00933     if (Run_region_bounds) {
00934       Set_Error_Phase("Generate Region Boundaries");
00935       Generate_region_boundaries(pu, alias_mgr);
00936     }
00937 
00938     // region loop
00939     // 1) This iterator first finds the enclosing block for each region so
00940     //    the region can be replaced once it it processed.
00941     // 2) REGION_remove_and mark pulls the region out of the WHIRL tree
00942     //    so we can process it independently, put back by
00943     //    REGION_replace_from_mark
00944     // 3) Process_pragma_options changes the compile options based on region
00945     //    pragmas in the code.
00946     
00947     REGION_CS_ITER_init(&rgn_iter, pu);
00948     for (REGION_CS_NoEarlierSub_First(&rgn_iter, pu,
00949            (RID_TYPE)(RID_TYPE_olimit | RID_TYPE_pragma | RID_TYPE_loop));
00950          REGION_CS_NoEarlierSub_While(&rgn_iter);
00951          REGION_CS_NoEarlierSub_Next(&rgn_iter)) {
00952       WN *rwn;
00953       BOOL need_options_pop;
00954 
00955       rwn = REGION_remove_and_mark(pu, &rgn_iter);
00956 
00957       Is_True(rwn != NULL, ("BE driver, IR inconsistency, WOPT-CG loop"));
00958       Is_True(REGION_get_rid(rwn) != NULL, ("BE driver, NULL RID"));
00959       Is_True(RID_type(REGION_get_rid(rwn)) != RID_TYPE_undefined,
00960               ("BE driver, undefined RID type"));
00961 
00962       Set_Current_Region_For_Trace( RID_id(REGION_get_rid(rwn)) );
00963 
00964       if (Get_Trace(TP_REGION,TT_REGION_ALL)) {
00965         fprintf(TFile,"===== BE driver, WOPT-CG loop: %s %d, stacked=%d\n",
00966                 REGION_CS_ITER_is_pu(&rgn_iter) ? "PU" : "RGN",
00967                 RID_id(REGION_get_rid(rwn)),
00968                 !REGION_CS_ITER_is_not_stacked(&rgn_iter));
00969         RID_WN_Tree_Print(TFile, rwn);
00970       }
00971 
00972       // process any region or PU level options pragmas
00973       { RID *rid = REGION_get_rid(rwn);
00974         Is_True(rid != NULL, ("BE driver, NULL rid inside region loop"));
00975         if (RID_options(rid) != NULL) {
00976           Options_Stack->Process_Pragma_Options(RID_options(rid));
00977           need_options_pop = TRUE;
00978         } else
00979           need_options_pop = FALSE;
00980       }
00981 
00982       if (Show_Progress) {
00983         if (rwn != pu)
00984           fprintf(stderr, "... compiling region (%d)\n", 
00985                   RID_id(REGION_get_rid(rwn)));
00986         else if (!cg_one_time)  /* must have had regions in pu */
00987           fprintf(stderr, "... compiling program unit\n");
00988       }
00989       /* if we are processing a region, add that to the name */
00990       Save_Cur_PU_Name (ST_name(PU_Info_proc_sym(current_pu)), 
00991                         RID_id(REGION_get_rid(rwn)));
00992 
00993       /* Add instrumentation here for wopt. */
00994       if (Instrumentation_Enabled
00995           && Instrumentation_Phase_Num == PROFILE_PHASE_BEFORE_WOPT) {
00996         WN_Instrument(rwn, PROFILE_PHASE_BEFORE_WOPT); 
00997       } else if (Feedback_Enabled[PROFILE_PHASE_BEFORE_WOPT]) {
00998         WN_Annotate(rwn, PROFILE_PHASE_BEFORE_WOPT, &MEM_pu_pool);
00999       }
01000       Set_Error_Phase ( "Before WOPT" );
01001 
01002       if (Run_wopt) {
01003         rwn = WOPT_Processing (current_pu, pu, &rgn_iter, rwn);
01004         if (WN_opcode(rwn) == OPC_FUNC_ENTRY)
01005           Verify_SYMTAB (CURRENT_SYMTAB);
01006         if ( Cur_PU_Feedback ) {
01007           Cur_PU_Feedback->Verify("after WOPT");
01008         }
01009 #if 0  // this is now unnecessary because the lowering is done inside wopt
01010         if (Only_Unsigned_64_Bit_Ops && Delay_U64_Lowering)
01011           U64_lower_wn(rwn, FALSE);
01012 #endif
01013       }
01014 
01015       /* we may still have to print the .O file:                   */
01016       /* (Olimit stops optimization for one PU but not all)        */
01017       /* only write .O file for PU, no need to replace region      */
01018       /* because REGION_remove_and_mark does nothing for pu        */
01019       if (need_wopt_output && REGION_CS_ITER_is_not_stacked(&rgn_iter)) {
01020         Set_PU_Info_tree_ptr(current_pu, rwn);
01021         Write_PU_Info(current_pu);
01022       }
01023 
01024 
01025       /* in case wopt cleared it (temporary backwards-compatibility) */
01026       Save_Cur_PU_Name (ST_name(PU_Info_proc_sym(current_pu)), 
01027                 RID_id(REGION_get_rid(rwn)));
01028 
01029       /* Add instrumentation here for cg. */
01030       if (Instrumentation_Enabled
01031           && Instrumentation_Phase_Num == PROFILE_PHASE_BEFORE_CG) {
01032         rwn = WN_Lower(rwn, LOWER_SCF, NULL, 
01033                        "Lower structured control flow");
01034         WN_Instrument(rwn, PROFILE_PHASE_BEFORE_CG);
01035 #if 0
01036         extern void wb_gwe(WN*); // hack to check __profile calls.
01037         wb_gwe(rwn);
01038 #endif
01039       } else if (Feedback_Enabled[PROFILE_PHASE_BEFORE_CG]) {
01040         rwn = WN_Lower(rwn, LOWER_SCF, NULL, 
01041                        "Lower structured control flow");
01042         WN_Annotate(rwn, PROFILE_PHASE_BEFORE_CG, &MEM_pu_pool);
01043       }
01044       Set_Error_Phase ( "Before CG" );
01045 
01046       if (Run_cg) { /* lower for cg */
01047         Set_Error_Phase ("Lowering");
01048         WB_LWR_Initialize(rwn, alias_mgr);
01049         rwn = WN_Lower(rwn, LOWER_TO_CG, alias_mgr, "Lowering to CG");
01050         if (Only_Unsigned_64_Bit_Ops && ! Run_wopt)
01051           U64_lower_wn(rwn, FALSE);
01052         WB_LWR_Terminate();
01053         if (Get_Trace(TP_REGION,TT_REGION_ALL)) {
01054           fprintf(TFile,"===== driver, after lowering\n");
01055           RID_WN_Tree_Print(TFile,rwn);
01056         }
01057 
01058         if ( Cur_PU_Feedback ) {
01059           Cur_PU_Feedback->Verify("after LOWER_TO_CG");
01060         }
01061 
01062         if (cg_one_time) {  /* do this before processing part of PU */
01063           cg_one_time = FALSE;
01064           /* move data layout to after whirl lowering   */
01065           Set_Error_Phase("Data Layout");
01066           /* look over whole PU and calculate size of actual area */
01067           Calculate_Stack_Frame_Sizes (rwn);    
01068           CG_PU_Initialize(pu);
01069         }
01070 
01071         if (!REGION_CS_ITER_is_not_stacked(&rgn_iter) ||
01072             !REGION_CS_ITER_is_pu(&rgn_iter)) { /* pass over region */
01073           DST_IDX tmp_idx;
01074           WN *compiled_block;
01075           tmp_idx.byte_idx = DST_INVALID_BYTE_IDX; /* mark DST as NULL */
01076           FmtAssert(PU_has_region (Get_Current_PU ()),
01077                     ("BE driver, found region when SYMTAB_has_rgn is off"));
01078           if (Get_Trace(TP_REGION,TT_REGION_ALL)) {
01079             fprintf(TFile,
01080                     "===== driver, before CG_Generate_Code (region)\n");
01081             RID_WN_Tree_Print(TFile,rwn);
01082             RID_set_print(TFile,REGION_get_rid(rwn));
01083           }
01084           compiled_block = CG_Generate_Code(rwn, alias_mgr, tmp_idx, TRUE);
01085           rwn = compiled_block;
01086           if (Get_Trace(TP_REGION,TT_REGION_ALL)) {
01087             fprintf(TFile,
01088                     "===== driver, after CG_Generate_Code\n");
01089             RID_WN_Tree_Print(TFile,rwn);
01090           }
01091         } // if (!REGION_CS_ITER_is_not_stacked(&rgn_iter) ||
01092       } // if (Run_cg)
01093 
01094       if (REGION_CS_ITER_is_not_stacked(&rgn_iter)) /* this is tricky */
01095         pu = rwn;
01096       REGION_replace_from_mark(rwn, &rgn_iter);
01097       // put options back the way they were
01098       if (need_options_pop)
01099         Options_Stack->Pop_Current_Options();
01100       if (Get_Trace(TP_REGION,TT_REGION_ALL)) {
01101         fprintf(TFile,
01102                 "------------ bottom of WOPT-CG loop: ------------\n");
01103         Is_True(REGION_consistency_check(pu),(""));
01104         RID_WN_Tree_Print(TFile,pu);
01105         if (Run_cg)
01106           fdump_region_tree(TFile,pu);
01107         else
01108           fdump_tree(TFile,pu);
01109         fprintf(TFile,"--------------------------------------------\n");
01110       }
01111       if (rwn != pu)
01112         Report_CG_Region_Timing ( Tim_File, Cur_PU_Name );
01113     }
01114     Verify_SYMTAB (CURRENT_SYMTAB);
01115     return pu;
01116 } /* Do_WOPT_and_CG_with_Regions */
01117 
01118 
01119 static void
01120 Post_Process_Backend (PU_Info *current_pu, WN *pu)
01121 {
01122   if (Run_cg) {
01123     if (Get_Trace(TP_REGION,TT_REGION_ALL)) {
01124       fprintf(TFile,"BE driver, Post_Process_Backend "
01125               "+++++++++++++++++++++++++++++++\n");
01126       RID_WN_Tree_Print(TFile,pu);
01127       fdump_region_tree(TFile,pu);
01128       fprintf(TFile,"BE driver, Post_Process_Backend "
01129               "+++++++++++++++++++++++++++++++\n");
01130       fprintf(TFile,"Right before CG_Generate_Code (PU)\n");
01131     }
01132 
01133     CG_Generate_Code(pu, alias_mgr, PU_Info_pu_dst(current_pu), FALSE);
01134     CG_PU_Finalize();
01135   }
01136   // Delete alias manager after CG finished, PV 525127, 527977
01137   if (alias_mgr) {
01138     Delete_Alias_Manager(alias_mgr, MEM_pu_nz_pool_ptr);
01139     alias_mgr = NULL;
01140   }
01141 } /* Post_Process_Backend */
01142 
01143 
01144 
01145 extern "C" {
01146   extern void Process_Fill_Align_Pragmas (WN* func_wn);
01147   extern void Rewrite_Pragmas_On_Structs (WN* block_wn, WN* wn);
01148 }
01149 
01150 /***********************************************************************
01151  *
01152  * Find all EH regions in the PU, and mark their INITOs as used.
01153  *
01154  ***********************************************************************/
01155 static void Update_EHRegion_Inito_Used (WN *wn) {
01156   if (!wn) return;
01157   
01158   OPERATOR opr = WN_operator(wn);
01159 
01160   if (opr == OPR_REGION && WN_ereg_supp(wn)) {
01161     INITO_IDX ino_idx = WN_ereg_supp(wn);
01162     ST *st = INITO_st(ino_idx);
01163     Clear_ST_is_not_used(st);
01164   }
01165 
01166   // now recurse
01167   if (opr == OPR_BLOCK) {
01168     WN *kid = WN_first (wn);
01169     while (kid) {
01170       Update_EHRegion_Inito_Used(kid);
01171       kid = WN_next(kid);
01172     }
01173   } else {
01174     for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
01175       Update_EHRegion_Inito_Used(WN_kid(wn,kidno));
01176     }
01177   }
01178 }
01179 
01180 /***********************************************************************
01181  *
01182  * This pass is called after preopt+lno+mplowering. 
01183  * Any of those passes may have deleted EH-regions, but left the
01184  * INITO sts for those regions hanging around.
01185  * This pass will search for all used INITOs, and mark the rest unused.
01186  *
01187  ***********************************************************************/
01188 static void Update_EHRegion_Inito (WN *pu) {
01189   INT i;
01190   INITO *ino;
01191 
01192   // first mark all EH-region STs unused.
01193   FOREACH_INITO (CURRENT_SYMTAB, ino, i) {
01194     ST *st = INITO_st(ino);
01195     if (ST_sclass(st) == SCLASS_EH_REGION ||
01196         ST_sclass(st) == SCLASS_EH_REGION_SUPP) {
01197       Set_ST_is_not_used(st);
01198     }
01199   }
01200 
01201   // now find INITO sts that are referenced in WHIRL,
01202   // and mark them used.
01203   Update_EHRegion_Inito_Used (pu);
01204 }
01205 
01206 static void
01207 Backend_Processing (PU_Info *current_pu, WN *pu)
01208 {
01209     {
01210         /* Always process the first PU for fill-align, since that one contains
01211          * the pragmas for global symbols. And, because of IPA, we cannot
01212          * depend on the SYMTAB_id being 1 for the first PU.
01213          */
01214         static BOOL done_first_pu = FALSE;
01215         BOOL needs_fill_align_lowering =
01216             PU_needs_fill_align_lowering (Get_Current_PU ());
01217         if (needs_fill_align_lowering || !done_first_pu) {
01218             Process_Fill_Align_Pragmas (pu);
01219             done_first_pu = TRUE;
01220         }
01221     }
01222 
01223     PU_adjust_addr_flags(Get_Current_PU_ST(), pu);
01224 
01225     if (Run_MemCtr)
01226         MemCtr_Add (pu);
01227 
01228     /* Make sure that RETURN_VAL nodes, Return_Val_Preg references and
01229        MLDID/MSTID nodes have been lowered. This requires its own pass
01230        because it may have to go back to change the previous CALL statement
01231        to add a fake parameter. */
01232     if (WHIRL_Return_Val_On || WHIRL_Mldid_Mstid_On) {
01233         Is_True(WHIRL_Return_Val_On && WHIRL_Mldid_Mstid_On,
01234                 ("-INTERNAL:return_val and -INTERNAL:mldid_mstid must be on the same time"));
01235         pu = WN_Lower (pu, LOWER_RETURN_VAL | LOWER_MLDID_MSTID, NULL,
01236                        "RETURN_VAL & MLDID/MSTID lowering");
01237     }
01238 
01239     /* If early mp processing has been requested, then do it before running
01240        lno/preopt. */
01241     BOOL has_mp = PU_has_mp (Get_Current_PU ());
01242     if (has_mp && Early_MP_Processing) {
01243         Set_PU_Info_depgraph_ptr(Current_PU_Info,Current_Dep_Graph);
01244         Set_PU_Info_state(Current_PU_Info,WT_DEPGRAPH,Subsect_InMem);
01245 
01246         Set_Error_Phase ( "MP Lowering" );
01247         WB_LWR_Initialize(pu, NULL);
01248         pu = WN_Lower (pu, LOWER_MP, NULL, "Before MP Lowering");
01249         WB_LWR_Terminate();
01250     }
01251 
01252     /* Add instrumentation here for lno. */
01253     if( Instrumentation_Enabled
01254        && Instrumentation_Phase_Num == PROFILE_PHASE_BEFORE_LNO ) {
01255         WN_Instrument(pu, PROFILE_PHASE_BEFORE_LNO); 
01256     } else if ( Feedback_Enabled[PROFILE_PHASE_BEFORE_LNO] ) {
01257       WN_Annotate(pu, PROFILE_PHASE_BEFORE_LNO, &MEM_pu_pool);   
01258     }
01259     Set_Error_Phase ( "LNO Processing" );
01260 
01261     if (Run_lno || Run_Distr_Array || Run_preopt || Run_autopar) {
01262         pu = LNO_Processing (current_pu, pu);/* make -O0, -O1, -O2 a bit faster*/
01263         if (Run_autopar)
01264             Rewrite_Pragmas_On_Structs (NULL, WN_func_body(pu));
01265     }
01266 
01267     /* First round output (.N file, w2c, w2f, etc.) */
01268     Set_Error_Phase ( "Post LNO Processing" );
01269     Post_LNO_Processing (current_pu, pu);
01270     if (!Run_wopt && !Run_cg) return;
01271 
01272     Verify_SYMTAB (CURRENT_SYMTAB);
01273 
01274     /* If no early mp processing has been requested, then do it after running
01275      * lno/preopt. Do this whether or not wopt is to be run.
01276      * If we were just running LNO,
01277      * then the above call to Post_LNO_Processing has written out the
01278      * WHIRL file and thereby mangled current_pu, so we cannot do the
01279      * MP lowering.
01280      * To support an option to see post-LNO, post MP-lowered output,
01281      * maybe we can just move the call to the lowerer before
01282      * Post_LNO_Processing.
01283      */
01284     has_mp = PU_has_mp (Get_Current_PU ());
01285     if (has_mp && !Early_MP_Processing) {
01286         Set_Error_Phase ( "MP Lowering" );
01287         WB_LWR_Initialize(pu, NULL);
01288         pu = WN_Lower (pu, LOWER_MP, NULL, "Before MP Lowering");
01289         WB_LWR_Terminate();
01290     }
01291 
01292     Update_EHRegion_Inito (pu);
01293 
01294     /* Generate EH range table for PU.  The high and low labels are
01295      * filled in during code generation.
01296      */
01297     if (Run_cg) 
01298         EH_Generate_Range_List(pu);
01299 
01300     BOOL save_run_wopt = Run_wopt;
01301     // I believe I can assert that WN_operator(pu) == OPR_FUNC_ENTRY
01302     // here, but I won't, simply because I don't need to. Might as
01303     // well check. -- RK 990713
01304     if (Run_wopt &&
01305         (WN_operator(pu) == OPR_FUNC_ENTRY) &&
01306         ST_asm_function_st(*WN_st(pu))) {
01307       // Throttle WOPT; we don't want it for PU's that merely wrap up
01308       // file-scope asm statements.
01309       Run_wopt = FALSE;
01310     }
01311 
01312     Set_Error_Phase ( "WOPT/CG Processing" );
01313     pu = Do_WOPT_and_CG_with_Regions (current_pu, pu);
01314 
01315     Run_wopt = save_run_wopt;
01316 
01317     Set_Error_Phase ( "Post Backend Processing" );
01318     Post_Process_Backend (current_pu, pu);
01319 
01320 } /* Backend_Processing */
01321 
01322 static WN *
01323 Preprocess_PU (PU_Info *current_pu)
01324 {
01325   WN *pu = NULL;
01326 
01327   Initialize_PU_Stats ();  /* Needed for Olimit as well as tracing */
01328 
01329   Current_PU_Info = current_pu;
01330   MEM_POOL_Push(MEM_pu_nz_pool_ptr);
01331   MEM_POOL_Push(MEM_pu_pool_ptr);
01332 
01333   Cur_PU_Feedback    = NULL;
01334 
01335   BOOL is_mp_nested_pu = FALSE;
01336 
01337   /* read from mmap area */
01338   Start_Timer ( T_ReadIR_CU );
01339   // The current PU could already be memory as happens when the
01340   // compiler creates it during back end compilation of an earlier PU. 
01341   if (PU_Info_state (current_pu, WT_TREE) != Subsect_InMem) {
01342     Read_Local_Info (MEM_pu_nz_pool_ptr, current_pu);
01343     if (PU_Info_state (current_pu, WT_FEEDBACK) == Subsect_InMem) {
01344         const Pu_Hdr* pu_hdr = (const Pu_Hdr*)
01345             PU_Info_feedback_ptr (current_pu);
01346         Cur_PU_Feedback = CXX_NEW (FEEDBACK (PU_Info_tree_ptr (current_pu),
01347                                              MEM_pu_nz_pool_ptr,
01348                                              pu_hdr->pu_num_inv_entries,
01349                                              pu_hdr->pu_num_br_entries,
01350                                              pu_hdr->pu_num_loop_entries,
01351                                              pu_hdr->pu_num_scircuit_entries,
01352                                              pu_hdr->pu_num_call_entries,
01353                                              pu_hdr->pu_num_switch_entries),
01354                                    MEM_pu_nz_pool_ptr);
01355         Read_Feedback_Info (Cur_PU_Feedback, PU_Info_tree_ptr (current_pu),
01356                             *pu_hdr);
01357         // turn off other feedback I/O
01358         Instrumentation_Enabled = FALSE;
01359         memset (Feedback_Enabled, '\0', PROFILE_PHASE_LAST * sizeof(BOOL));
01360     } else
01361         Cur_PU_Feedback = NULL;
01362   } else {                          /* retrieve transferred maps */
01363       // change some globals to define current_pu as the current PU
01364     Current_Map_Tab = PU_Info_maptab(current_pu);
01365     Current_pu = &PU_Info_pu(current_pu);
01366     CURRENT_SYMTAB = PU_lexical_level(*Current_pu);
01367     if ((PU_is_nested_func(*Current_pu) && PU_mp(*Current_pu)) ||
01368         Is_Set_PU_Info_flags(current_pu, PU_IS_DRA_CLONE)) {
01369       is_mp_nested_pu = TRUE;
01370       // hack to restore nested PU's symtab
01371       Restore_Local_Symtab(current_pu);
01372 
01373       if (PU_Info_state (current_pu, WT_FEEDBACK) == Subsect_InMem) {
01374               // Restore FEEDBACK object allocated by MP lowerer
01375           Cur_PU_Feedback = (FEEDBACK *) PU_Info_feedback_ptr (current_pu);
01376           Is_True(Cur_PU_Feedback, ("invalid PU_Info for feedback"));
01377               // turn off other feedback I/O
01378           Instrumentation_Enabled = FALSE;
01379           memset(Feedback_Enabled, '\0', PROFILE_PHASE_LAST * sizeof(BOOL));
01380       } else
01381           Cur_PU_Feedback = NULL;
01382     } else {
01383       Is_True(FALSE, ("Robert doesn't understand where symtabs come from"));
01384     }
01385   }
01386 
01387   BE_symtab_alloc_scope_level(CURRENT_SYMTAB);
01388   Scope_tab[CURRENT_SYMTAB].st_tab->Register(*Be_scope_tab[CURRENT_SYMTAB].be_st_tab);
01389 
01390   /* NOTE: "pu" is not defined until this point, since the actual
01391    * (WN *) is calculated by Read_Local_Info().
01392    */
01393   pu = PU_Info_tree_ptr(current_pu);
01394 
01395   /* Disable all prompf processing for PUs generated by the compiler,
01396    * such as cloned subroutines, with exception of mp routines which
01397    * we do want to process (we just don't want to do the static
01398    * analysis part for them).  
01399    *
01400    * TODO:  Disable Anl_Static_Analysis() when this condition holds,
01401    * but generate the subroutines in the .m file and have the cloner
01402    * assign an ID map for the subroutine with unique ID numbers.
01403    */
01404   if (!Saved_run_prompf                                          &&
01405       Run_prompf                                                 &&
01406       Is_Set_PU_Info_flags(current_pu, PU_IS_COMPILER_GENERATED) &&
01407       !PU_mp (Get_Current_PU ())) {
01408     Saved_run_prompf = Run_prompf;
01409     Saved_run_w2c = Run_w2c;
01410     Saved_run_w2f = Run_w2f;
01411     Saved_run_w2fc_early = Run_w2fc_early;
01412     Run_prompf = FALSE;
01413     Run_w2c = FALSE;
01414     Run_w2f = FALSE;
01415     Run_w2fc_early = FALSE;
01416   }
01417 
01418   /* store original pu name */
01419   Orig_PU_Name = Get_Orig_PU_Name(current_pu);
01420   Save_Cur_PU_Name(ST_name(PU_Info_proc_sym(current_pu)), 0);
01421 
01422   Set_Current_PU_For_Trace(ST_name(PU_Info_proc_sym(current_pu)), 
01423                            Current_PU_Count());
01424 
01425   Stop_Timer (T_ReadIR_CU);
01426   Check_for_IR_Dump(TP_IR_READ,pu,"IR_READ");
01427 
01428   if (Show_Progress) {
01429     fprintf(stderr, "Compiling %s(%d)\n",
01430             ST_name(PU_Info_proc_sym(current_pu)),
01431             Current_PU_Count());
01432   }
01433 
01434   if (Get_Trace(TP_REGION,TT_REGION_ALL)) {
01435     fprintf(TFile,"===== BE driver, PU loop: PU %s(%d)\n",
01436             ST_name(PU_Info_proc_sym(current_pu)),Current_PU_Count());
01437   }
01438 
01439   if (Tlog_File) {
01440     fprintf(Tlog_File,"BEGIN %s\n",ST_name(PU_Info_proc_sym(current_pu)));
01441   }
01442 
01443   WN_Mem_Push ();
01444 
01445   if (Run_wopt || Run_cg) {         /* PU level initialization for lowerer */
01446     Lowering_Initialize();
01447   }
01448 
01449   if (Run_prompf && 
01450       !Is_Set_PU_Info_flags(current_pu, PU_IS_COMPILER_GENERATED)) {
01451     Prompf_Id_Map = Anl_Init_Map(MEM_pu_pool_ptr); 
01452     WB_ANL_Initialize(pu, Prompf_Id_Map); 
01453     Anl_Static_Analysis(pu, Prompf_Id_Map);
01454     WB_ANL_Terminate(); 
01455   }
01456 
01457   if (Run_purple) {
01458     Prp_Instrument_And_EmitSrc(pu);
01459   }
01460 
01461   /* Add instrumentation here for vho lower. */
01462   if ( Instrumentation_Enabled
01463        && Instrumentation_Phase_Num == PROFILE_PHASE_BEFORE_VHO ) {
01464     if (!is_mp_nested_pu )
01465       WN_Instrument(pu, PROFILE_PHASE_BEFORE_VHO); 
01466 #if 0
01467     extern void wb_gwe(WN*); // hack to check __profile calls.
01468     wb_gwe(pu);
01469 #endif
01470   } else if ( Feedback_Enabled[PROFILE_PHASE_BEFORE_VHO] ) {
01471     WN_Annotate(pu, PROFILE_PHASE_BEFORE_VHO, &MEM_pu_pool);
01472   }
01473 
01474   pu = VHO_Lower_Driver (current_pu, pu);
01475 
01476   if ( Cur_PU_Feedback ) {
01477     Cur_PU_Feedback->Verify("after VHO lower");
01478   }
01479 
01480   pu = Adjust_Opt_Level (current_pu, pu, ST_name(PU_Info_proc_sym(current_pu)));
01481 
01482   if (wopt_loaded) {
01483     Create_Restricted_Map(MEM_pu_nz_pool_ptr);
01484   }
01485 
01486   /* Always create region pool because there are many 
01487    * places where they can be introduced. Needed for PUs 
01488    * with no regions also */
01489   /* NOTE: part of what REGION_initialize does can be moved
01490    * to when the .B file is read in. */
01491   REGION_Initialize (pu, PU_has_region (Get_Current_PU ()));
01492   return pu;
01493 } /* Preprocess_PU */
01494 
01495 static void
01496 Postprocess_PU (PU_Info *current_pu)
01497 {
01498   if (Tlog_File) {
01499     fprintf (Tlog_File, "END %s\n", ST_name(PU_Info_proc_sym(current_pu)));
01500   }
01501 
01502   Current_Map_Tab = PU_Info_maptab(current_pu);
01503  
01504   REGION_Finalize();
01505 
01506   if (Run_wopt || Run_cg) {
01507     // delete lowering map
01508     Lowering_Finalize();
01509   }
01510 
01511   // Delete alias manager after CG finished ? PV 525127, 527977
01512   WN_Mem_Pop (); // WN pool
01513 
01514   if (wopt_loaded) {
01515     Delete_Restricted_Map();
01516   }
01517 
01518   SYMTAB_IDX scope_level = PU_lexical_level(PU_Info_pu(current_pu));
01519 
01520   Scope_tab[scope_level].st_tab->
01521     Un_register(*Be_scope_tab[scope_level].be_st_tab);
01522   Be_scope_tab[scope_level].be_st_tab->Clear();
01523 
01524   Free_Local_Info(current_pu); // deletes all maps
01525   MEM_POOL_Pop(MEM_pu_nz_pool_ptr);
01526   MEM_POOL_Pop(MEM_pu_pool_ptr);
01527 
01528   /* Re-enable prompf processing if relevant.  
01529    *
01530    * TODO:  Disable Anl_Static_Analysis() when this condition holds,
01531    * but generate the subroutines in the .m file and have the cloner
01532    * assign an ID map for the subroutine with unique ID numbers.
01533    */
01534   if (Saved_run_prompf) {
01535     Run_prompf = Saved_run_prompf;
01536     Run_w2c = Saved_run_w2c;
01537     Run_w2f = Saved_run_w2f;
01538     Run_w2fc_early = Saved_run_w2fc_early;
01539     Saved_run_prompf = FALSE;
01540     Saved_run_w2c = FALSE;
01541     Saved_run_w2f = FALSE;
01542     Saved_run_w2fc_early = FALSE;
01543   }
01544 } /* Postprocess_PU */
01545 
01546 /* compile each PU through all phases before going to the next PU */
01547 static void
01548 Preorder_Process_PUs (PU_Info *current_pu)
01549 {
01550   INT orig_opt_level = Opt_Level;
01551   BOOL orig_run_lno = Run_lno;
01552   BOOL orig_run_preopt = Run_preopt;
01553   BOOL orig_run_wopt = Run_wopt;
01554   BOOL orig_olimit_opt = Olimit_opt;
01555 
01556   WN *pu;
01557   Start_Timer(T_BE_PU_CU);
01558 
01559   pu = Preprocess_PU(current_pu);
01560 
01561   // Quick! Before anyone risks creating any PREGs in the back end,
01562   // register the back end's PREG table with the main PREG table so
01563   // they will grow together as PREGs are created.
01564   Scope_tab[CURRENT_SYMTAB].preg_tab->Register(Be_preg_tab);
01565 
01566   WN_verifier(pu);
01567 
01568   Verify_SYMTAB (CURRENT_SYMTAB);
01569 
01570   if (!PU_mp (Get_Current_PU ()) &&
01571       (Run_Dsm_Cloner || Run_Dsm_Common_Check || Run_Dsm_Check))
01572     DRA_Processing(current_pu, pu, Cur_PU_Feedback != NULL);
01573 
01574   /* If SYMTAB_IPA_on is set then we have run ipl,
01575    * and therefore already done OMP_prelowering.
01576    * So don't do it again.
01577    */
01578   if (PU_has_mp (Get_Current_PU ()) && !FILE_INFO_ipa (File_info)) {
01579     Set_Error_Phase("OMP Pre-lowering");
01580     WB_OMP_Initialize(pu, Prompf_Id_Map);
01581     pu = OMP_Prelower(current_pu, pu);
01582     WB_OMP_Terminate(); 
01583   }
01584 
01585   if (Run_ipl) {
01586     Ipl_Processing (current_pu, pu);
01587     Verify_SYMTAB (CURRENT_SYMTAB);
01588   }
01589   else {
01590     Backend_Processing (current_pu, pu);
01591     Verify_SYMTAB (CURRENT_SYMTAB);
01592   }
01593   if (reset_opt_level) {
01594     Opt_Level = orig_opt_level;
01595     Run_lno = orig_run_lno;
01596     Run_preopt = orig_run_preopt;
01597     Run_wopt = orig_run_wopt;
01598     reset_opt_level = FALSE;
01599     Olimit_opt = orig_olimit_opt;
01600   }
01601 
01602   Scope_tab[CURRENT_SYMTAB].preg_tab->Un_register(Be_preg_tab);
01603   Be_preg_tab.Clear();
01604 
01605   Stop_Timer(T_BE_PU_CU);
01606   Finish_BE_Timing ( Tim_File, ST_name(PU_Info_proc_sym(current_pu)) );
01607   Advance_Current_PU_Count();
01608 
01609   Cur_PU_Name = NULL;           // memory will not be leaked; eventual
01610                                 // pop occurs in Postprocess_PU's call
01611                                 // to WN_MEM_Pop. Reset here is
01612                                 // required so Save_Cur_PU_Name will
01613                                 // not misbehave.
01614 
01615   // Print miscellaneous statistics to trace file:
01616   Print_PU_Stats ();
01617 
01618   // Now recursively process the child PU's.
01619 
01620   for (PU_Info *child = PU_Info_child(current_pu);
01621        child != NULL;
01622        child = PU_Info_next(child)) {
01623     Preorder_Process_PUs(child);
01624   }
01625 
01626   Postprocess_PU (current_pu);
01627 } /* Preorder_Process_PUs */
01628 
01629 static void Print_Tlog_Header(INT argc, char **argv)
01630 {
01631   INT i;
01632   if (Get_Trace(TP_PTRACE1, TP_PTRACE1_NOHDR))
01633     return; 
01634   fprintf(Tlog_File,"1.0\n"); /* initial version number */
01635   fprintf(Tlog_File,"{ ");
01636   for (i=0; i<argc; i++)
01637     fprintf(Tlog_File,"%s ", argv[i]);
01638   fprintf(Tlog_File,"}\n");
01639 }
01640 
01641 
01642 #define FEEDBACK_PATH_MAXLEN 1024
01643 
01644 
01645 static void
01646 Process_Feedback_Options (OPTION_LIST* olist)
01647 {
01648   if (Feedback_File_Name) {
01649     // this is the case where feedback files are specified implicitly.
01650     // We need to search the directory
01651 
01652     // Find last '/' in path
01653     INT t = strlen(Feedback_File_Name);
01654     Is_True(t < FEEDBACK_PATH_MAXLEN - 16,
01655             ("Process_Feedback_Options: Feedback file name too long(%d)",
01656              t));
01657     while (t > 0 && Feedback_File_Name[t - 1] != '/')
01658       t--;
01659 
01660     // Separate Feedback_File_Name into directory(path) and a file
01661     // name prefix.  The last character in path must be '/', so that
01662     // feedback file names can be appended.
01663     char path[FEEDBACK_PATH_MAXLEN];
01664     char *prefix = Feedback_File_Name + t;
01665     if (t > 0) {
01666       // Split at the '/'
01667       strncpy(path, Feedback_File_Name, t);
01668     } else {
01669       // No '/' in Feedback_File_Name; use "./" for current directory
01670       path[0] = '.';
01671       path[1] = '/';
01672       t = 2;
01673     }
01674     path[t] = '\0';
01675     char *dir_end = path + t;
01676 
01677     INT prefix_len = strlen(prefix);
01678     DIR* dirp = opendir(path);
01679     struct dirent* direntp;
01680     while ((direntp = readdir(dirp)) != NULL) {
01681       if (strncmp(direntp->d_name, prefix, prefix_len) == 0) {
01682         strcpy(dir_end, direntp->d_name);
01683         Process_Feedback_File(path);
01684       }
01685     }
01686     closedir(dirp);
01687   }
01688 
01689   OPTION_LIST *ol;
01690   for (ol = olist; ol != NULL; ol = OLIST_next(ol)) {
01691     char *val = OLIST_val(ol);
01692     Process_Feedback_File(val);
01693   }
01694 } // Process_Feedback_Options
01695 
01696 
01697 // Provide a place to stop after components are loaded
01698 extern "C" {
01699   void be_debug(void) {}
01700 }
01701 
01702 INT
01703 main (INT argc, char **argv)
01704 {
01705   INT local_ecount, local_wcount;
01706   PU_Info *pu_tree;
01707   
01708   setlinebuf (stdout);
01709   setlinebuf (stderr);
01710   Handle_Signals ();
01711   MEM_Initialize ();
01712   Cur_PU_Name = NULL;
01713   Init_Error_Handler ( 100 );
01714   Set_Error_Line ( ERROR_LINE_UNKNOWN );
01715   Set_Error_File ( NULL );
01716   Set_Error_Phase ( "Back End Driver" );
01717 
01718   Preconfigure ();
01719   Process_Command_Line (argc, argv);
01720   if (Inhibit_EH_opt && Opt_Level > 1) Opt_Level = 1;
01721   Reset_Timers ();
01722   Start_Timer(T_BE_Comp);
01723   Prepare_Source ();
01724   Initialize_Stats ();
01725   Configure ();
01726   Configure_Source(NULL); /* Most configuration variables are set here */
01727 #ifdef Is_True_On
01728   if (Get_Trace (TKIND_ALLOC, TP_MISC)) {
01729     MEM_Tracing_Enable();
01730   }
01731 #endif
01732   if ( List_Enabled ) {
01733     Prepare_Listing_File ();
01734     List_Compile_Options ( Lst_File, "", FALSE, List_All_Options, FALSE );
01735   }
01736 
01737   Init_Operator_To_Opcode_Table();
01738     
01739   /* decide which phase to call */
01740   load_components (argc, argv);
01741   be_debug();
01742 
01743   MEM_POOL_Push (&MEM_src_pool);
01744   MEM_POOL_Push (&MEM_src_nz_pool);
01745   if ( Show_Progress ) {
01746     fprintf ( stderr, "Compiling %s (%s) -- Back End\n",
01747              Src_File_Name, Irb_File_Name );
01748     fflush ( stderr );
01749   }
01750   Set_Error_Source (Src_File_Name);
01751 
01752   // Push initial file level options
01753   Options_Stack = CXX_NEW(OPTIONS_STACK(&MEM_src_nz_pool), &MEM_src_nz_pool);
01754   Options_Stack->Push_Current_Options();
01755 
01756   Start_Timer (T_ReadIR_Comp);
01757   if (Read_Global_Data) {
01758         // get input from two separate files
01759         Irb_File = (FILE *)Open_Global_Input (Global_File_Name);
01760         Irb_File = (FILE *)Open_Local_Input (Irb_File_Name);
01761   }
01762   else {
01763         Irb_File = (FILE *)Open_Input_Info (Irb_File_Name);
01764   }
01765   Initialize_Symbol_Tables (FALSE);
01766   New_Scope (GLOBAL_SYMTAB, Malloc_Mem_Pool, FALSE);
01767   pu_tree = Read_Global_Info (NULL);
01768   Stop_Timer (T_ReadIR_Comp);
01769 
01770   Initialize_Special_Global_Symbols ();
01771 
01772   // if compiling an ipa-generated file, do not instrument phases that
01773   // have already been done at ipl time.
01774   if (FILE_INFO_ipa (File_info)) {
01775       if (Instrumentation_Enabled &&
01776           Instrumentation_Phase_Num <= PROFILE_PHASE_IPA_CUTOFF) {
01777           Instrumentation_Enabled = FALSE;
01778           Instrumentation_Phase_Num = PROFILE_PHASE_NONE;
01779       }
01780   } else {
01781       Process_Feedback_Options (Feedback_Option);
01782   }
01783 
01784   //
01785   // Ordinarily DRA_Initialize() would run as part of Phase_Init(),
01786   // but we need to run it early, right here. 
01787   // The reason is that this code does a pre-scan to determine whether
01788   // any cloning might be required, and if so, sets the mp_needs_lno
01789   // bit in file_info. We need to know that before we do any
01790   // initialization and setup processing for dra/lego (e.g. loading
01791   // lno/wopt, doing lego_init, etc.
01792   //
01793   if (Run_Dsm_Cloner || Run_Dsm_Common_Check) {
01794     DRA_Initialize();
01795   }
01796   BOOL needs_lno = FILE_INFO_needs_lno (File_info);
01797 
01798   if (needs_lno && !Run_ipl) {
01799     Run_Distr_Array = TRUE;
01800     if (!Run_lno && !Run_autopar) {
01801       /* ipl is not running, and LNO has not been loaded */
01802       /* Has distributed arrays, so load LNO, initialize, and setup */
01803       INT phase_argc;
01804       char **phase_argv;
01805 
01806       if (!Run_wopt && !Run_preopt) {
01807         /* load wopt */
01808         Get_Phase_Args (PHASE_WOPT, &phase_argc, &phase_argv);
01809         load_so ("wopt" DSOext, WOPT_Path, Show_Progress);
01810         wopt_main (phase_argc, phase_argv, argc, argv);
01811         wopt_loaded = TRUE;
01812       }
01813 
01814       Get_Phase_Args (PHASE_LNO, &phase_argc, &phase_argv);
01815       load_so ("lno" DSOext, LNO_Path, Show_Progress);
01816       lno_main (phase_argc, phase_argv, argc, argv);
01817     }
01818   }
01819 
01820   /* initialize the BE symtab. Note that w2cf relies on the BE_ST */
01821   /* during Phase_Init and Phase_Fini                             */
01822 
01823   BE_symtab_initialize_be_scopes();
01824   BE_symtab_alloc_scope_level(GLOBAL_SYMTAB);
01825   SYMTAB_IDX scope_level;
01826   for (scope_level = 0;
01827        scope_level <= GLOBAL_SYMTAB;
01828        ++scope_level) {
01829     // No need to deal with levels that don't have st_tab's. Currently
01830     // this should be only zero.
01831     if (Scope_tab[scope_level].st_tab != NULL) {
01832       Scope_tab[scope_level].st_tab->
01833         Register(*Be_scope_tab[scope_level].be_st_tab);
01834     }
01835     else {
01836       Is_True(scope_level == 0,
01837               ("Nonexistent st_tab for level %d", scope_level));
01838     }
01839   }
01840 
01841   Phase_Init ();
01842 
01843   if (Run_preopt || Run_wopt || Run_lno || Run_Distr_Array || Run_autopar 
01844         || Run_cg) {
01845     Set_Error_Descriptor (EP_BE, EDESC_BE);
01846     Set_Error_Descriptor (EP_CG, EDESC_CG);
01847   }
01848 
01849   if (Tlog_File)
01850     Print_Tlog_Header(argc, argv);
01851 
01852 
01853   for (PU_Info *current_pu = pu_tree;
01854        current_pu != NULL;
01855        current_pu = PU_Info_next(current_pu)) {
01856     Preorder_Process_PUs(current_pu);
01857   }
01858 
01859 
01860   /* Terminate stdout line if showing PUs: */
01861   if (Show_Progress) {
01862     fprintf (stderr, "\n");
01863     fflush (stderr);
01864   }
01865 
01866   Phase_Fini ();
01867 
01868   /* free the BE symtabs. w2cf requires BE_ST in Phase_Fini */
01869 
01870   Is_True(scope_level == GLOBAL_SYMTAB + 1,
01871           ("scope_level must be GLOBAL_SYMTAB + 1, left from earlier loop"));
01872 
01873   do {
01874     --scope_level;
01875     // No need to deal with levels that don't have st_tab's. Currently
01876     // this should be only zero.
01877     if (Scope_tab[scope_level].st_tab != NULL) {
01878       Scope_tab[scope_level].st_tab->
01879         Un_register(*Be_scope_tab[scope_level].be_st_tab);
01880       Be_scope_tab[scope_level].be_st_tab->Clear();
01881     }
01882     else {
01883       Is_True(scope_level == 0,
01884               ("Nonexistent st_tab for level %d", scope_level));
01885     }
01886   } while (scope_level != 0);
01887 
01888   BE_symtab_free_be_scopes();
01889 
01890   
01891   if (need_wopt_output || need_lno_output || need_ipl_output) {
01892     Write_Global_Info (pu_tree);
01893     if (need_ipl_output)
01894       Ipl_Extra_Output (ir_output);
01895     Close_Output_Info ();
01896   }
01897   else if (Emit_Global_Data) {
01898     Write_Global_Info (NULL);   /* even if dummy pu, don't write any pu's */
01899     Close_Output_Info ();
01900   }
01901 
01902   /* Print miscellaneous statistics to trace file: */
01903   Print_Total_Stats ();
01904   if ((Opt_Level > 0 || Run_autopar) 
01905         && Max_Src_Olimit > Olimit && !Olimit_opt && Show_OPT_Warnings) {
01906     ErrMsg (EC_File_Olimit_Exceeded, Max_Src_Olimit);
01907   }
01908     
01909   Stop_Timer(T_BE_Comp);
01910   Finish_Compilation_Timing ( Tim_File, Src_File_Name );
01911 
01912   MEM_POOL_Pop ( &MEM_src_pool );
01913   MEM_POOL_Pop ( &MEM_src_nz_pool );
01914 #ifdef Is_True_On
01915         if (Get_Trace (TKIND_ALLOC, TP_MISC)) {
01916             fprintf (TFile, "\n%s\tMemory allocation information after be\n", DBar);
01917             MEM_Trace ();
01918         }
01919 #endif
01920 
01921   /* If we've seen errors, note them and terminate: */
01922   if ( Get_Error_Count ( &local_ecount, &local_wcount ) ) {
01923     ecount += local_ecount;
01924   }
01925  
01926   if ( ecount > 0 ) {
01927     Terminate(Had_Internal_Error() ? RC_INTERNAL_ERROR : RC_NORECOVER_USER_ERROR) ;
01928   }
01929 
01930   /* Close and delete files as necessary: */
01931   Cleanup_Files ( TRUE, FALSE );
01932 
01933   exit ( RC_OKAY );
01934   /*NOTREACHED*/
01935 
01936 } /* main */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines