00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #define __STDC_LIMIT_MACROS
00045 #include <stdint.h>
00046 #if defined(BUILD_OS_DARWIN)
00047 #include <darwin_elf.h>
00048 #else
00049 #include <elf.h>
00050 #endif
00051 #include <sys/types.h>
00052
00053 #ifdef KEY
00054 #include <linux/limits.h>
00055 #endif
00056
00057 #include "defs.h"
00058 #include "symtab.h"
00059 #include "wn.h"
00060 #define USE_DST_INTERNALS // needed by pu_info.h
00061 #include "pu_info.h"
00062
00063 #ifndef BACK_END
00064 #define BACK_END // needed by ir_bwrite.h
00065 #endif
00066 #include "ir_bwrite.h"
00067
00068 #include "erglob.h"
00069
00070 #include "ipa_option.h"
00071 #include "ipa_cg.h"
00072 #include "ipaa.h"
00073 #include "ipc_compile.h"
00074 #include "ipc_dst_merge.h"
00075 #include "ipc_dst_utils.h"
00076 #include "ipo_alias_class.h"
00077 #include "ipo_defs.h"
00078
00079 #include "ipo_main.h"
00080
00081 #include <cmplrs/host.h>
00082 #include "ld_ipa_option.h"
00083 #include "ipc_weak.h"
00084
00085 #ifdef KEY
00086 #include "ipa_builtins.h"
00087 #include "ir_bcom.h"
00088 #include "be_ipa_util.h"
00089 #endif
00090
00091
00092 extern "C" void add_to_tmp_file_list (char*);
00093 #pragma weak add_to_tmp_file_list
00094
00095 extern "C" char* create_unique_file (const char*, char);
00096 #pragma weak create_unique_file
00097
00098 extern "C" char* create_tmp_file (char*);
00099 #pragma weak create_tmp_file
00100
00101
00102
00103
00104
00105 typedef vector<PU_Info*> DUMMY_GLOBAL_PRAGMA_PU;
00106 DUMMY_GLOBAL_PRAGMA_PU dummy_pu_list;
00107
00108 static PU_Info *
00109 Write_Dummy_PUs (Output_File* output_file);
00110
00111 namespace {
00112
00113 struct externize {
00114 void operator()(UINT32 , ST* st) const {
00115 if (ST_sym_class(*st) == CLASS_FUNC &&
00116 ! PU_has_global_pragmas (Pu_Table[ST_pu (st)]))
00117 Set_ST_storage_class(*st, SCLASS_EXTERN);
00118 }
00119 };
00120
00121 }
00122
00123 extern "C" char* IP_global_symtab_name(void)
00124 {
00125 static char* symtab_file_name = 0;
00126
00127 if (!symtab_file_name)
00128 symtab_file_name = create_unique_file("symtab", 'I');
00129
00130 Is_True(symtab_file_name != 0 && strlen(symtab_file_name) != 0,
00131 ("IP_global_symtab_name failed to create unique filename"));
00132
00133 return symtab_file_name;
00134 }
00135
00136 extern "C" void IP_write_global_symtab(void)
00137 {
00138 Temporary_Error_Phase ephase("Writing WHIRL file");
00139
00140 static bool already_written = false;
00141 Is_True(!already_written,
00142 ("IP_write_global_symtab may only be called once"));
00143 already_written = true;
00144
00145
00146 For_all(St_Table, 1, externize());
00147
00148 char* const symtab_file_name = IP_global_symtab_name();
00149 Output_File* symtab_file = WN_open_output(symtab_file_name);
00150 if (!symtab_file)
00151 ErrMsg ( EC_IR_Create, symtab_file_name, errno);
00152
00153 PU_Info *pu_tree = NULL;
00154 if (! dummy_pu_list.empty ()) {
00155 pu_tree = Write_Dummy_PUs (symtab_file);
00156 DST_TYPE merged_dst = IPC_merge_DSTs(pu_tree, Malloc_Mem_Pool);
00157
00158 WN_write_PU_Infos (pu_tree, symtab_file);
00159 WN_write_dst(merged_dst, symtab_file);
00160 } else {
00161
00162 WN_write_PU_Infos (NULL, symtab_file);
00163
00164 DST_TYPE empty_dst = DST_create(Malloc_Mem_Pool, 10);
00165 DST_mk_compile_unit(empty_dst, Malloc_Mem_Pool, DST_INVALID_IDX,
00166 "", "", "",
00167 DW_LANG_lo_user,
00168 DW_ID_case_sensitive);
00169 WN_write_dst(empty_dst, symtab_file);
00170 }
00171
00172 WN_write_globals(symtab_file);
00173 WN_write_strtab(Index_To_Str(0), STR_Table_Size(), symtab_file);
00174 #ifdef KEY
00175 if (Mod_Ref_Info_Table_Size() != 0)
00176 IPA_write_summary (IPA_irb_write_mod_ref_info, symtab_file);
00177 #endif
00178 WN_write_revision(symtab_file);
00179
00180 add_to_tmp_file_list(symtab_file_name);
00181 WN_close_output(symtab_file);
00182 free(symtab_file);
00183 }
00184
00185 void
00186 IP_WRITE_pu_internal (PU_Info* pu, Output_File *outfile)
00187 {
00188 Is_True(pu != 0, ("IP_WRITE_pu_internal: pu must not be null"));
00189
00190 WN_MAP off_map = WN_MAP_UNDEFINED;
00191
00192
00193 IPA_NODE_CONTEXT context (Get_Node_From_PU(pu));
00194
00195 Is_True(CURRENT_SYMTAB > GLOBAL_SYMTAB,
00196 ("Lexical level of pu %s is %d, shouldn't be less than %d.",
00197 ST_name(St_Table[PU_Info_proc_sym(pu)]),
00198 CURRENT_SYMTAB,
00199 GLOBAL_SYMTAB + 1));
00200
00201 WN_write_symtab (pu, outfile);
00202
00203 if (PU_Info_state(pu, WT_AC_INTERNAL) == Subsect_InMem) {
00204 Is_True(PU_Info_state(pu, WT_ALIAS_CLASS) == Subsect_Missing,
00205 ("IP_WRITE_pu_internal: Only one alias class subsection "
00206 "at a time, please."));
00207 Write_AC_INTERNAL_Map = TRUE;
00208 Write_ALIAS_CLASS_Map = FALSE;
00209 }
00210 if (PU_Info_state(pu, WT_ALIAS_CLASS) == Subsect_InMem) {
00211 Is_True(PU_Info_state(pu, WT_AC_INTERNAL) == Subsect_Written,
00212 ("IP_WRITE_pu_internal: AC_INTERNAL subsection must be "
00213 "written."));
00214 Write_AC_INTERNAL_Map = FALSE;
00215 Write_ALIAS_CLASS_Map = TRUE;
00216 }
00217
00218 MEM_POOL_Push(MEM_local_nz_pool_ptr);
00219 off_map = WN_MAP32_Create(MEM_local_nz_pool_ptr);
00220
00221 if (IPA_Enable_Alias_Class) {
00222 Is_True(PU_Info_state(pu, WT_AC_INTERNAL) == Subsect_InMem,
00223 ("IP_WRITE_pu_internal: AC_INTERNAL subsection "
00224 "must be in memory"));
00225 Is_True((Write_ALIAS_CLASS_Map != 0) != (Write_AC_INTERNAL_Map != 0),
00226 ("IP_WRITE_pu_internal: Exactly one ALIAS_CLASS mapping must "
00227 "be written"));
00228 Is_True(((PU_Info_state(pu, WT_ALIAS_CLASS) == Subsect_InMem) ==
00229 (Write_ALIAS_CLASS_Map != 0)),
00230 ("IP_WRITE_pu_internal: Write_ALIAS_CLASS_Map inconsistent "
00231 "with internal state"));
00232 }
00233
00234 if (PU_Info_state (pu, WT_FEEDBACK) == Subsect_InMem)
00235 WN_write_feedback (pu, outfile);
00236
00237 WN_write_tree (pu, off_map, outfile);
00238
00239 if (Write_ALIAS_CLASS_Map || Write_AC_INTERNAL_Map) {
00240
00241 if (Write_AC_INTERNAL_Map) {
00242 WN_write_voidptr_map(pu, off_map, outfile, WT_AC_INTERNAL,
00243 WN_MAP_AC_INTERNAL,
00244 "alias class intermediate map");
00245 }
00246
00247 if (Write_ALIAS_CLASS_Map) {
00248 WN_write_INT32_map(pu, off_map, outfile, WT_ALIAS_CLASS,
00249 WN_MAP_ALIAS_CLASS, "alias class map");
00250 }
00251
00252 WN_MAP_Delete(off_map);
00253 MEM_POOL_Pop(MEM_local_nz_pool_ptr);
00254 }
00255 }
00256
00257
00258 void IP_write_PU_tree(Output_File* f, PU_Info* pu) {
00259 IP_WRITE_pu_internal(pu, f);
00260
00261
00262 PU_Info* prev_child = NULL;
00263 PU_Info* child = PU_Info_child(pu);
00264 while (child) {
00265 IPA_NODE* node = Get_Node_From_PU(child);
00266 IP_FILE_HDR& hdr = node->File_Header();
00267 IP_PROC_INFO& info = IP_FILE_HDR_proc_info(hdr)[node->Proc_Info_Index()];
00268 IPA_STATE_TYPE state = IP_PROC_INFO_state(info);
00269
00270 Is_True(state == IPA_ORIG || state == IPA_MODIFIED ||
00271 state == IPA_WRITTEN || state == IPA_DELETED,
00272 ("PU %s has unexpected state %d",
00273 ST_name(St_Table[PU_Info_proc_sym(child)]),
00274 IP_PROC_INFO_state(info)));
00275
00276 if (state != IPA_DELETED) {
00277 IP_write_PU_tree(f, child);
00278 Set_IP_PROC_INFO_state(info, IPA_WRITTEN);
00279 prev_child = child;
00280 }
00281 else {
00282 if (prev_child == NULL) {
00283 PU_Info_child(pu) = PU_Info_next(child);
00284 }
00285 else {
00286 PU_Info_next(prev_child) = PU_Info_next(child);
00287 }
00288 }
00289 child = PU_Info_next(child);
00290 }
00291 }
00292
00293
00294
00295 PU_Info* copy_pu_tree(PU_Info* old_pu, MEM_POOL* p) {
00296 Is_True(old_pu != 0, ("copy_pu_tree: null pu pointer"));
00297 Is_True(p != 0, ("copy_pu_tree: null mempool pointer"));
00298
00299 PU_Info* result = CXX_NEW(PU_Info(*old_pu), p);
00300 PU_Info_next(result) = 0;
00301
00302 if (PU_Info_child(old_pu)) {
00303 PU_Info* cur = PU_Info_child(old_pu);
00304 PU_Info* tail = copy_pu_tree(cur, p);
00305 PU_Info_child(result) = tail;
00306
00307 cur = PU_Info_next(cur);
00308 while (cur) {
00309 PU_Info_next(tail) = copy_pu_tree(cur, p);
00310 cur = PU_Info_next(cur);
00311 tail = PU_Info_next(tail);
00312 }
00313 }
00314
00315 return result;
00316 }
00317
00318
00319 static PU_Info*
00320 Write_Dummy_PUs (Output_File* output_file)
00321 {
00322 PU_Info *pu_tree = NULL;
00323 for (DUMMY_GLOBAL_PRAGMA_PU::const_iterator it (dummy_pu_list.begin ());
00324 it != dummy_pu_list.end (); ++it) {
00325
00326 PU_Info* pu = *it;
00327 Is_True(pu != 0, ("IPA output queue: pu must not be null"));
00328 Is_True(PU_lexical_level(&St_Table[PU_Info_proc_sym(pu)]) ==
00329 GLOBAL_SYMTAB + 1,
00330 ("IPA output queue is only for global pu's"));
00331
00332 IP_write_PU_tree(output_file, pu);
00333
00334
00335 PU_Info* new_pu = copy_pu_tree(pu, Malloc_Mem_Pool);
00336 PU_Info_next(new_pu) = pu_tree;
00337 pu_tree = new_pu;
00338 }
00339
00340 return pu_tree;
00341 }
00342
00343
00344 extern void WN_free_input (void *handle, off_t mapped_size);
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 template <class Vector>
00359 void free_pu_cg_resources(PU_Info* pu, Vector& file_hdr_list)
00360 {
00361 Is_True(pu != 0, ("destroy_pu_tree: null pu pointer"));
00362
00363
00364 if (PU_Info_child(pu))
00365 free_pu_cg_resources(PU_Info_child(pu), file_hdr_list);
00366
00367
00368 for ( ; pu ; pu = PU_Info_next(pu)) {
00369 IPA_NODE* node = Get_Node_From_PU(pu);
00370
00371 #ifdef KEY
00372
00373 if (node->Is_Builtin()) {
00374 if (node->Mod_Ref_Info ())
00375 node->Mod_Ref_Info ()->Free_Ref_Sets ();
00376 node->Set_Processed();
00377 continue;
00378 }
00379 #endif
00380
00381
00382 IP_FILE_HDR& hdr = node->File_Header();
00383 Is_True(IP_PROC_INFO_state(
00384 IP_FILE_HDR_proc_info(hdr)[node->Proc_Info_Index()])
00385 == IPA_WRITTEN,
00386 ("pu %s is not flagged as written",
00387 ST_name(St_Table[PU_Info_proc_sym(pu)])));
00388 file_hdr_list.push_back(&hdr);
00389
00390
00391 if (node->Mod_Ref_Info ())
00392 node->Mod_Ref_Info ()->Free_Ref_Sets ();
00393 MEM_POOL_Delete(node->Mem_Pool());
00394 node->File_Header().num_written++;
00395 if (node->File_Header().num_written == IP_FILE_HDR_num_procs(node->File_Header()))
00396 WN_free_input(IP_FILE_HDR_input_map_addr(node->File_Header()), node->File_Header().mapped_size);
00397 node->Clear_Mempool_Initialized();
00398 node->Set_Processed();
00399 }
00400 }
00401
00402
00403
00404 struct file_hdr_ptr_cmp {
00405 bool operator()(IP_FILE_HDR* x, IP_FILE_HDR* y) const {
00406 return reinterpret_cast<unsigned long>(x) <
00407 reinterpret_cast<unsigned long>(y);
00408 }
00409 };
00410
00411
00412 void free_pu_resources(PU_Info* pu_tree, MEM_POOL* pool) {
00413 typedef std::vector<IP_FILE_HDR*, mempool_allocator<IP_FILE_HDR*> >
00414 FILE_HDR_LIST_TYPE;
00415 FILE_HDR_LIST_TYPE file_hdr_list(pool);
00416
00417
00418
00419 free_pu_cg_resources(pu_tree, file_hdr_list);
00420 Is_True(file_hdr_list.size() >= 1, ("free_pu_resources: no file headers"));
00421
00422
00423 sort(file_hdr_list.begin(), file_hdr_list.end(), file_hdr_ptr_cmp());
00424 FILE_HDR_LIST_TYPE::iterator new_end =
00425 std::unique(file_hdr_list.begin(), file_hdr_list.end());
00426 file_hdr_list.erase(new_end, file_hdr_list.end());
00427 Is_True(file_hdr_list.size() >= 1, ("free_pu_resources: no file headers"));
00428
00429 Is_True(std::find(file_hdr_list.begin(), file_hdr_list.end(),
00430 static_cast<IP_FILE_HDR*>(0)) == file_hdr_list.end(),
00431 ("free_pu_resources: file hdr list contains a null pointer"));
00432
00433
00434
00435 for (FILE_HDR_LIST_TYPE::iterator it = file_hdr_list.begin();
00436 it != file_hdr_list.end();
00437 ++it)
00438 if (IP_FILE_HDR_all_procs_processed(**it))
00439 Destroy_File_Header(**it);
00440 }
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457 class output_queue {
00458 private:
00459 PU_Info* head;
00460 PU_Info* tail;
00461 Output_File* out_file;
00462 UINT32 nfiles;
00463 UINT32 ProMP_next_idx;
00464
00465 MEM_POOL pool;
00466
00467 public:
00468 output_queue();
00469 ~output_queue();
00470
00471
00472 bool empty() const;
00473
00474
00475
00476
00477
00478
00479 bool should_flush(const IPA_NODE* node);
00480
00481
00482
00483 void push(PU_Info* pu);
00484
00485
00486
00487
00488 void flush();
00489
00490 private:
00491
00492 size_t pu_tree_add_comments(size_t index, size_t count, PU_Info* head);
00493
00494
00495 void open_output_file();
00496
00497
00498 void close_output_file();
00499 };
00500
00501
00502
00503 output_queue::output_queue()
00504 : head(0), tail(0), out_file(0), nfiles(0), ProMP_next_idx (1), pool()
00505 {}
00506
00507 output_queue::~output_queue()
00508 {
00509 Is_True(head == 0, ("IPA output queue has not been flushed"));
00510 }
00511
00512
00513 bool output_queue::empty() const {
00514 Is_True(head == 0 || out_file != 0,
00515 ("IPA output queue is not empty, but no output file exists"));
00516 Is_True(out_file == 0 || head != 0,
00517 ("IPA output file exists, but output queue is empty"));
00518
00519 return head == 0;
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 bool output_queue::should_flush(const IPA_NODE* node)
00537 {
00538 static UINT32 promp_id = 1;
00539 static UINT32 count = 0;
00540 count += node->Weight ();
00541
00542 #ifdef KEY
00543 if (IPA_Enable_Source_PU_Order || Opt_Options_Inconsistent)
00544 {
00545 if (IPA_NODE::next_file_id != -1 &&
00546 IPA_NODE::next_file_id != node->File_Id())
00547 {
00548
00549
00550 if (ProMP_Listing) {
00551 ProMP_next_idx = promp_id;
00552 promp_id = count;
00553 }
00554 count = 0;
00555 return TRUE;
00556 }
00557 }
00558 #endif
00559
00560 if (
00561 #ifdef KEY
00562
00563 !IPA_Enable_Source_PU_Order && !Opt_Options_Inconsistent &&
00564 #endif
00565 count >= IPA_Max_Output_File_Size) {
00566 if (ProMP_Listing) {
00567 ProMP_next_idx = promp_id;
00568 promp_id = count;
00569 }
00570 count = 0;
00571 return TRUE;
00572 } else
00573 return FALSE;
00574 }
00575
00576
00577
00578 void output_queue::push(PU_Info* pu) {
00579 Temporary_Error_Phase ephase("Writing WHIRL file");
00580
00581 Is_True(pu != 0, ("IPA output queue: pu must not be null"));
00582 Is_True(PU_lexical_level(&St_Table[PU_Info_proc_sym(pu)]) ==
00583 GLOBAL_SYMTAB + 1,
00584 ("IPA output queue is only for global pu's"));
00585
00586
00587 if (!out_file) {
00588 Is_True(head == 0 && tail == 0,
00589 ("No output file, but output queue is not empty"));
00590 if (nfiles == 0)
00591 MEM_POOL_Initialize(&pool, "IPA bwrite mempool", FALSE);
00592 this->open_output_file();
00593 MEM_POOL_Push_Freeze(&pool);
00594 }
00595
00596
00597 IP_write_PU_tree(out_file, pu);
00598
00599
00600 PU_Info* new_pu = copy_pu_tree(pu, &pool);
00601 if (head == 0)
00602 head = tail = new_pu;
00603 else {
00604 PU_Info_next(tail) = new_pu;
00605 tail = new_pu;
00606 }
00607
00608 #ifdef KEY
00609
00610
00611
00612
00613
00614 static int builtins_written = 0;
00615 if (!builtins_written) {
00616 builtins_written = 1;
00617
00618 std::vector<IPA_BUILTIN*>::iterator it;
00619 for (it = IPA_builtins_list.begin(); it != IPA_builtins_list.end(); it++) {
00620 IPA_BUILTIN *ipa_builtin = *it;
00621 PU_Info *pu_info = ipa_builtin->Get_PU_Info();
00622
00623
00624 IPA_NODE_CONTEXT context (Get_Node_From_PU(pu_info));
00625
00626 WN_write_symtab (pu_info, out_file);
00627
00628 WN_MAP off_map = WN_MAP_UNDEFINED;
00629 MEM_POOL_Push(MEM_local_nz_pool_ptr);
00630 off_map = WN_MAP32_Create(MEM_local_nz_pool_ptr);
00631
00632 WN_write_tree (pu_info, off_map, out_file);
00633
00634 WN_MAP_Delete(off_map);
00635 MEM_POOL_Pop(MEM_local_nz_pool_ptr);
00636
00637
00638 Is_True(head, ("output_queue::push() head is 0"));
00639 PU_Info* new_pu = copy_pu_tree(pu_info, &pool);
00640 PU_Info_next(tail) = new_pu;
00641 tail = new_pu;
00642 }
00643 }
00644 #endif
00645
00646 Is_True(!this->empty(), ("output_queue::push() failed"));
00647
00648 }
00649
00650 #ifdef KEY
00651
00652 static int
00653 count_new_lines (const char * pu_name)
00654 {
00655 int count = 0;
00656
00657 for (char c = *pu_name; c != '\0'; c = *(++pu_name))
00658 if (c == '\n')
00659 count++;
00660
00661 return count;
00662 }
00663
00664
00665
00666
00667
00668 static void
00669 fill_in_buffer (char * buf, int count, const char * pu_name)
00670 {
00671 sprintf(buf, " %d: ", count);
00672 buf = strchr(buf, '\0');
00673
00674 while (*pu_name != '\0')
00675 {
00676 *buf = *pu_name;
00677 if (*pu_name == '\n')
00678 {
00679 *(++buf) = '#';
00680 *(++buf) = '#';
00681 *(++buf) = ' ';
00682 }
00683 buf++;
00684 pu_name++;
00685 }
00686 *buf = '\0';
00687 }
00688 #endif
00689
00690 size_t
00691 output_queue::pu_tree_add_comments(size_t index, size_t count, PU_Info* head)
00692 {
00693 Is_True(head != 0, ("pu_tree_add_comments: no head"));
00694 while (head) {
00695 const size_t bufsize = 2048;
00696 const size_t padding = 16;
00697 static char static_buf[bufsize];
00698
00699 const char* pu_name = ST_name(St_Table[PU_Info_proc_sym(head)]);
00700 Is_True(pu_name != 0, ("pu_tree_add_comments: null pu name"));
00701
00702 char* buf = 0;
00703 const size_t pu_len = strlen(pu_name);
00704 #ifdef KEY
00705
00706 int num_new_lines = count_new_lines(pu_name);
00707 const int total_len = pu_len + padding + num_new_lines * 5;
00708 #else
00709 const int total_len = pu_len + padding;
00710 #endif
00711
00712 if (total_len < bufsize)
00713 buf = static_buf;
00714 else {
00715 buf = static_cast<char*>(malloc(total_len));
00716 if (!buf)
00717 ErrMsg (EC_No_Mem, "pu_tree_add_comment");
00718 }
00719
00720 #ifdef KEY
00721
00722
00723 if (num_new_lines)
00724 fill_in_buffer (buf, count++, pu_name);
00725 else
00726 #endif
00727
00728 sprintf(buf, " %lu: %s", (unsigned long)(count++), pu_name);
00729 ipacom_add_comment(index, buf);
00730
00731 if (buf != static_buf)
00732 free(buf);
00733
00734 if (PU_Info_child(head))
00735 count = pu_tree_add_comments(index, count, PU_Info_child(head));
00736 head = PU_Info_next(head);
00737 }
00738
00739 return count;
00740 }
00741
00742
00743
00744
00745 void output_queue::flush() {
00746 Temporary_Error_Phase ephase("Writing WHIRL file");
00747
00748 if (!this->empty()) {
00749
00750 if (IPA_Enable_ipacom) {
00751 const size_t index = ipacom_process_file(out_file->file_name, head,
00752 ProMP_next_idx);
00753 ipacom_add_comment(index, "pu's contained in this file:");
00754 pu_tree_add_comments(index, 0, head);
00755 }
00756
00757
00758
00759 DST_TYPE merged_dst = IPC_merge_DSTs(head, &pool);
00760 WN_write_PU_Infos(head, out_file);
00761 WN_write_dst(merged_dst, out_file);
00762
00763 #if defined(TARG_SL)
00764
00765 if (ld_ipa_opt[LD_IPA_IPISR].flag)
00766 WN_write_isr_cg(ipisr_cg, out_file);
00767 #endif // TARG_SL
00768
00769 WN_write_revision(out_file);
00770
00771 close_output_file();
00772 free_pu_resources(head, &pool);
00773
00774
00775 MEM_POOL_Pop_Unfreeze(&pool);
00776
00777
00778 head = 0;
00779 tail = 0;
00780 }
00781 }
00782
00783 void output_queue::open_output_file() {
00784 Temporary_Error_Phase ephase("Writing WHIRL file");
00785 Is_True(out_file == 0, ("ipa output queue: file is already open"));
00786
00787 char buffer[PATH_MAX];
00788 sprintf(buffer, "%u", ++nfiles);
00789 char* new_file_name = create_unique_file(buffer, 'I');
00790 Output_File* new_file = WN_open_output(new_file_name);
00791 if (!new_file) {
00792 ErrMsg ( EC_IR_Create, new_file_name, errno);
00793 }
00794 add_to_tmp_file_list(new_file->file_name);
00795 if (IPA_Enable_Alias_Class) {
00796
00797
00798 Ip_alias_class_files.push_back(new_file->file_name);
00799 }
00800 this->out_file = new_file;
00801 }
00802
00803 void output_queue::close_output_file() {
00804 Is_True(out_file != 0, ("ipa output queue: no file to close"));
00805 Is_True (nfiles > 0,
00806 ("ipa output queue: nfiles == %u, should be >= 1", nfiles));
00807
00808 WN_close_output(out_file);
00809 free(out_file);
00810 out_file = 0;
00811 }
00812
00813
00814
00815 output_queue Output_Queue;
00816
00817 static void
00818 clean_up_deleted_nested_pu_info(PU_Info* pu)
00819 {
00820 PU_Info* prev_child = NULL;
00821 PU_Info* child = PU_Info_child(pu);
00822 while (child) {
00823 ST* child_st = &St_Table[PU_Info_proc_sym(child)];
00824 if (ST_is_not_used (child_st) ) {
00825 if (prev_child == NULL) {
00826 PU_Info_child(pu) = PU_Info_next(child);
00827 }
00828 else {
00829 PU_Info_next(prev_child) = PU_Info_next(child);
00830 }
00831 }
00832 else
00833 prev_child = child;
00834 child = PU_Info_next(child);
00835 }
00836 }
00837
00838
00839
00840
00841
00842
00843
00844
00845 extern "C" void IP_WRITE_pu (IP_FILE_HDR *s , INT pindex)
00846 {
00847 Temporary_Error_Phase ephase("Writing WHIRL file");
00848
00849 Is_True(s != 0, ("IP_WRITE_pu: file header must not be null"));
00850 Is_True(pindex >= 0 && pindex < IP_FILE_HDR_num_procs(*s),
00851 ("IP_WRITE_pu: index %d out of range. Should be 0 <= index < %d",
00852 pindex, IP_FILE_HDR_num_procs(*s)));
00853
00854 IP_PROC_INFO* proc_info = IP_FILE_HDR_proc_info(*s) + pindex;
00855 Is_True(proc_info != 0, ("IP_WRITE_pu: proc_info must not be null"));
00856 FmtAssert(IP_PROC_INFO_state(*proc_info) != IPA_WRITTEN,
00857 ("IP_WRITE_pu: pu has already been written"));
00858 FmtAssert(IP_PROC_INFO_state(*proc_info) != IPA_UNUSED &&
00859 IP_PROC_INFO_state(*proc_info) != IPA_DELETED,
00860 ("IP_WRITE_pu: pu has bad state flag %d",
00861 IP_PROC_INFO_state(*proc_info)));
00862
00863
00864 Set_IP_PROC_INFO_state(*proc_info, IPA_WRITTEN);
00865 Inc_IP_FILE_HDR_num_procs_processed(*s);
00866
00867 PU_Info* pu = IP_PROC_INFO_pu_info(*proc_info);
00868
00869 if (pu) {
00870
00871
00872 clean_up_deleted_nested_pu_info(pu);
00873
00874 IPA_NODE* node = Get_Node_From_PU (pu);
00875
00876 if (IPA_Enable_Alias_Class) {
00877 Temporary_Error_Phase ephase("Alias class analysis");
00878
00879
00880 IPA_NODE_CONTEXT context (node);
00881
00882 Is_True(CURRENT_SYMTAB > GLOBAL_SYMTAB,
00883 ("Lexical level of pu %s is %d, shouldn't be less than %d.",
00884 ST_name(St_Table[PU_Info_proc_sym(pu)]),
00885 CURRENT_SYMTAB,
00886 GLOBAL_SYMTAB + 1));
00887
00888 #ifdef KEY
00889
00890 if (ST_class(St_Table[PU_Info_proc_sym(pu)]) != CLASS_NAME)
00891 #endif
00892 Ip_alias_class->Classify_memops(PU_Info_tree_ptr(pu));
00893
00894
00895
00896 Ip_alias_class->
00897 Classify_initialized_data(Scope_tab[CURRENT_SYMTAB].inito_tab);
00898
00899
00900
00901 Set_PU_Info_state(pu, WT_AC_INTERNAL, Subsect_InMem);
00902 }
00903
00904
00905 int lexical_level = PU_lexical_level(&St_Table[PU_Info_proc_sym(pu)]);
00906 Is_True(lexical_level >= GLOBAL_SYMTAB + 1,
00907 ("Lexical level of pu %s is %d, shouldn't be less than %d.",
00908 ST_name(St_Table[PU_Info_proc_sym(pu)]),
00909 lexical_level,
00910 GLOBAL_SYMTAB + 1));
00911 if (lexical_level == GLOBAL_SYMTAB + 1) {
00912 if (PU_has_global_pragmas (Get_Node_From_PU (pu)->Get_PU ())) {
00913 dummy_pu_list.push_back (pu);
00914 } else {
00915 Output_Queue.push(pu);
00916 if (Output_Queue.should_flush(node))
00917 IP_flush_output();
00918 }
00919 }
00920 }
00921 }
00922
00923 extern "C" void IP_flush_output(void)
00924 {
00925 Output_Queue.flush();
00926 }