Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 /* ==================================================================== 00037 * ==================================================================== 00038 * 00039 * 00040 * Revision history: 00041 * 13-Feb-95 - Original Version 00042 * 00043 * Description: 00044 * Main driver for the entire backend. 00045 * 00046 * ==================================================================== 00047 * ==================================================================== 00048 */ 00049 00050 #include <sys/types.h> 00051 #include <elf.h> /* for wn.h */ 00052 #include <cmplrs/rcodes.h> 00053 #include <dirent.h> 00054 #include <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 */