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 #ifdef USE_PCH 00036 #include "common_com_pch.h" 00037 #endif /* USE_PCH */ 00038 #pragma hdrstop 00039 #include <unistd.h> /* for close(), etc. */ 00040 #include <sys/stat.h> /* for fstat() */ 00041 #include <sys/mman.h> /* for mmap() */ 00042 #include <fcntl.h> /* for open() */ 00043 #include <elf.h> /* Open64 version */ 00044 #include <sys/elf_whirl.h> /* for WHIRL sections */ 00045 #include <errno.h> /* for error code */ 00046 00047 #ifndef USE_STANDARD_TYPES 00048 # define USE_STANDARD_TYPES /* override unwanted defines in "defs.h" */ 00049 #endif 00050 00051 #include "defs.h" /* for wn_core.h */ 00052 #include "alignof.h" /* for ALIGNOF() */ 00053 #ifdef OWN_ERROR_PACKAGE 00054 /* Turn off assertion in the opcode handling routines, we assume the tree 00055 * is clean. Also, this removes the dependency on "errors.h", which is not 00056 * used by all programs. 00057 */ 00058 #define Is_True(x,y) (0) 00059 #define ERRORS_INCLUDED 00060 #else 00061 #include "erglob.h" 00062 #endif 00063 #include "errors.h" 00064 #include "opcode.h" /* for wn_core.h */ 00065 #include "mempool.h" /* for MEM_POOL (for maps) */ 00066 #include "strtab.h" /* for strtab */ 00067 #include "symtab.h" /* for symtab */ 00068 #include "const.h" /* for constab */ 00069 #include "targ_const.h" /* for tcon */ 00070 #include "config_targ.h" /* for Target_ABI */ 00071 #include "config_debug.h" /* for ir_version_check */ 00072 #include "config_elf_targ.h" 00073 #include "irbdata.h" /* for init_data */ 00074 #include "wn_core.h" /* for WN */ 00075 #include "wn.h" /* for max_region_id */ 00076 #include "wn_map.h" /* for WN maps */ 00077 #define USE_DST_INTERNALS 00078 #include "dwarf_DST_mem.h" /* for dst */ 00079 #include "pu_info.h" 00080 #include "ir_elf.h" 00081 #include "ir_bwrite.h" 00082 #include "ir_bcom.h" 00083 #include "ir_bread.h" 00084 00085 #if defined(BACK_END) 00086 #include "xstats.h" 00087 #endif 00088 #if defined(BACK_END) || defined(BUILD_WNPREFETCH) 00089 #include "pf_cg.h" 00090 #endif 00091 00092 00093 00094 static BOOL verbose_info = FALSE; 00095 static WN *last_node = NULL; 00096 00097 static off_t global_mapped_size; 00098 static off_t local_mapped_size; 00099 00100 static char file_revision[80]; /* save revision string */ 00101 00102 00103 #define DOUBLE_ALIGNED(sz) (((sz) % 8) == 0 ? (sz) : (sz)+(8-((sz)%8))) 00104 #define ERROR_VALUE -1 00105 /* should be under Is_True_On, but we don't use that for ir_reader, 00106 * so add another define */ 00107 00108 #if defined(Is_True_On) || defined(DEBUG_IR) 00109 /* to make debugging easier, have all error returns go through this routine */ 00110 00111 INT 00112 Error_Return_Func (void) 00113 { 00114 if (verbose_info && last_node != NULL) { 00115 printf("last_node at %p, opcode = %s\n", 00116 last_node, OPCODE_name(WN_opcode(last_node))); 00117 } 00118 return ERROR_VALUE; 00119 } 00120 00121 #define ERROR_RETURN Error_Return_Func() 00122 #else 00123 #define ERROR_RETURN ERROR_VALUE 00124 #endif 00125 00126 00127 template <class Shdr> 00128 const Shdr* 00129 get_section_header (const Shdr* shdr, UINT n, Elf64_Word type, Elf64_Word info) 00130 { 00131 for (INT i = 1; i < n; ++i) { 00132 if (shdr[i].sh_type == type && shdr[i].sh_info == info) 00133 return shdr + i; 00134 } 00135 00136 return NULL; 00137 } 00138 00139 OFFSET_AND_SIZE 00140 get_section (void *handle, Elf64_Word type, Elf64_Word info) 00141 { 00142 if (handle == 0 || handle == (void *)(ERROR_VALUE)) { 00143 errno = EINVAL; 00144 return OFFSET_AND_SIZE (0, 0); 00145 } 00146 00147 errno = 0; 00148 00149 Elf64_Ehdr *eh = (Elf64_Ehdr *) handle; 00150 00151 #ifndef __ALWAYS_USE_64BIT_ELF__ 00152 if (eh->e_ident[EI_CLASS] == ELFCLASS32) { 00153 Elf32_Ehdr* ehdr = (Elf32_Ehdr*) handle; 00154 const Elf32_Shdr* shdr = (const Elf32_Shdr *) 00155 ((char *) handle + ehdr->e_shoff); 00156 shdr = get_section_header (shdr, ehdr->e_shnum, type, info); 00157 if (!shdr) 00158 return OFFSET_AND_SIZE (0, 0); 00159 return OFFSET_AND_SIZE (shdr->sh_offset, shdr->sh_size); 00160 } else 00161 #endif 00162 { 00163 const Elf64_Shdr* shdr = (const Elf64_Shdr *) 00164 ((char *) handle + eh->e_shoff); 00165 shdr = get_section_header (shdr, eh->e_shnum, type, info); 00166 if (!shdr) 00167 return OFFSET_AND_SIZE (0, 0); 00168 return OFFSET_AND_SIZE (shdr->sh_offset, shdr->sh_size); 00169 } 00170 } /* get_section */ 00171 00172 00173 /* If the CHECK_INPUT_FILES macro is defined, the binary reader tries to 00174 check for offsets that are outside the current (sub)section and for 00175 symbol table indices that are outside the valid ranges. To make the 00176 reading process as fast as possible, you can leave CHECK_INPUT_FILES 00177 undefined. */ 00178 00179 #if defined(Is_True_On) || defined(DEBUG_IR) 00180 #define CHECK_INPUT_FILES 00181 #endif 00182 00183 #ifdef CHECK_INPUT_FILES 00184 00185 #define CONVERT_OFFSET(typ, fld) \ 00186 if ((INTPTR)(fld) >= size) return ERROR_RETURN; \ 00187 else (fld) = (typ)(base + (INTPTR)(fld)) 00188 00189 #else 00190 00191 #define CONVERT_OFFSET(typ, fld) \ 00192 (fld) = (typ)(base + (INTPTR)(fld)) 00193 00194 #endif // CHECK_INPUT_FILES 00195 00196 00197 // read the global symbol table from the file and set up the various global 00198 // symtab data structures. try to reuse the mmap'ed memory buffer if 00199 // possible (i.e., avoid copying). 00200 00201 INT 00202 WN_get_global_symtab (void *handle) 00203 { 00204 00205 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_GLOBALS); 00206 if (shdr.offset == 0) 00207 return ERROR_RETURN; 00208 00209 const char *base = (char *) handle + shdr.offset; 00210 00211 const GLOBAL_SYMTAB_HEADER_TABLE *gsymtab = 00212 (GLOBAL_SYMTAB_HEADER_TABLE *) base; 00213 00214 UINT64 size = shdr.size; 00215 00216 if (gsymtab->size < sizeof(gsymtab) || 00217 gsymtab->entries < GLOBAL_SYMTAB_TABLES || gsymtab->size > size) 00218 return ERROR_RETURN; 00219 00220 UINT i; 00221 for (i = 0; i < GLOBAL_SYMTAB_TABLES; ++i) 00222 if (gsymtab->header[i].offset + gsymtab->header[i].size > size) 00223 return ERROR_RETURN; 00224 00225 for (i = 0; i < GLOBAL_SYMTAB_TABLES; ++i) { 00226 const SYMTAB_HEADER& hdr = gsymtab->header[i]; 00227 const char *addr = base + hdr.offset; 00228 00229 switch (hdr.type) { 00230 00231 case SHDR_FILE: 00232 File_info = *((FILE_INFO *) addr); 00233 break; 00234 00235 case SHDR_ST: 00236 Scope_tab[GLOBAL_SYMTAB].st_tab-> 00237 Transfer ((ST *) addr, hdr.size / hdr.entsize); 00238 break; 00239 00240 case SHDR_TY: 00241 Ty_tab.Transfer ((TY *) addr, hdr.size / hdr.entsize); 00242 break; 00243 00244 case SHDR_PU: 00245 Pu_Table.Transfer ((PU *) addr, hdr.size / hdr.entsize); 00246 break; 00247 00248 case SHDR_FLD: 00249 Fld_Table.Transfer ((FLD *) addr, hdr.size / hdr.entsize); 00250 break; 00251 00252 case SHDR_ARB: 00253 Arb_Table.Transfer ((ARB *) addr, hdr.size / hdr.entsize); 00254 break; 00255 00256 case SHDR_TYLIST: 00257 Tylist_Table.Transfer ((TYLIST *) addr, hdr.size / hdr.entsize); 00258 break; 00259 00260 case SHDR_TCON: 00261 Tcon_Table.Transfer ((TCON *) addr, hdr.size / hdr.entsize); 00262 break; 00263 00264 case SHDR_STR: 00265 Initialize_TCON_strtab (addr, hdr.size); 00266 break; 00267 00268 case SHDR_INITO: 00269 Scope_tab[GLOBAL_SYMTAB].inito_tab-> 00270 Transfer ((INITO *) addr, hdr.size / hdr.entsize); 00271 break; 00272 00273 case SHDR_INITV: 00274 Initv_Table.Transfer ((INITV *) addr, hdr.size / hdr.entsize); 00275 break; 00276 00277 case SHDR_BLK: 00278 Blk_Table.Transfer ((BLK *) addr, hdr.size / hdr.entsize); 00279 break; 00280 00281 case SHDR_ST_ATTR: 00282 Scope_tab[GLOBAL_SYMTAB].st_attr_tab-> 00283 Transfer ((ST_ATTR *) addr, hdr.size / hdr.entsize); 00284 break; 00285 } 00286 } 00287 00288 return 0; 00289 } // WN_get_global_symtab 00290 00291 00292 /* Given a handle returned by WN_open_input(), this function 00293 * sets up the SCOPE structure. 00294 * Returns -1 if error, 0 if success. 00295 * Assume that global symtab and string table are already read. 00296 */ 00297 00298 INT 00299 WN_get_symtab (void *handle, PU_Info *pu) 00300 { 00301 Subsect_State st = PU_Info_state(pu, WT_SYMTAB); 00302 if (st == Subsect_InMem) 00303 return 0; 00304 else if (st != Subsect_Exists) 00305 return ERROR_RETURN; 00306 00307 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_PU_SECTION); 00308 if (shdr.offset == 0) 00309 return ERROR_RETURN; 00310 00311 const char *base = (char *) handle + shdr.offset + 00312 PU_Info_subsect_offset (pu, WT_SYMTAB); 00313 Elf64_Word size = PU_Info_subsect_size(pu, WT_SYMTAB); 00314 const LOCAL_SYMTAB_HEADER_TABLE *lsymtab = 00315 (LOCAL_SYMTAB_HEADER_TABLE *) base; 00316 00317 if (lsymtab->size < sizeof(lsymtab) || 00318 lsymtab->entries < LOCAL_SYMTAB_TABLES || lsymtab->size > size) { 00319 errno = EINVAL; 00320 return ERROR_RETURN; 00321 } 00322 00323 UINT i; 00324 for (i = 0; i < LOCAL_SYMTAB_TABLES; ++i) 00325 if (lsymtab->header[i].offset + lsymtab->header[i].size > size) { 00326 errno = EINVAL; 00327 return ERROR_RETURN; 00328 } 00329 00330 for (i = 0; i < LOCAL_SYMTAB_TABLES; ++i) { 00331 const SYMTAB_HEADER& hdr = lsymtab->header[i]; 00332 const char *addr = base + hdr.offset; 00333 00334 switch (hdr.type) { 00335 00336 case SHDR_ST: 00337 Is_True(Scope_tab[CURRENT_SYMTAB].st_tab != 0, 00338 ("Null st_tab, level = %d", CURRENT_SYMTAB)); 00339 Scope_tab[CURRENT_SYMTAB].st_tab-> 00340 Transfer ((ST *) addr, hdr.size / hdr.entsize); 00341 break; 00342 00343 case SHDR_LABEL: 00344 Is_True(Scope_tab[CURRENT_SYMTAB].label_tab != 0, 00345 ("Null label_tab, level = %d", CURRENT_SYMTAB)); 00346 Scope_tab[CURRENT_SYMTAB].label_tab-> 00347 Transfer ((LABEL *) addr, hdr.size / hdr.entsize); 00348 break; 00349 00350 case SHDR_PREG: 00351 Is_True(Scope_tab[CURRENT_SYMTAB].preg_tab != 0, 00352 ("Null preg_tab, level = %d", CURRENT_SYMTAB)); 00353 Scope_tab[CURRENT_SYMTAB].preg_tab-> 00354 Transfer ((PREG *) addr, hdr.size / hdr.entsize); 00355 break; 00356 00357 case SHDR_INITO: 00358 Is_True(Scope_tab[CURRENT_SYMTAB].inito_tab != 0, 00359 ("Null inito_tab, level = %d", CURRENT_SYMTAB)); 00360 Scope_tab[CURRENT_SYMTAB].inito_tab-> 00361 Transfer ((INITO *) addr, hdr.size / hdr.entsize); 00362 break; 00363 00364 case SHDR_ST_ATTR: 00365 Is_True(Scope_tab[CURRENT_SYMTAB].st_attr_tab != 0, 00366 ("Null st_attr_tab, level = %d", CURRENT_SYMTAB)); 00367 Scope_tab[CURRENT_SYMTAB].st_attr_tab-> 00368 Transfer ((ST_ATTR *) addr, hdr.size / hdr.entsize); 00369 break; 00370 } 00371 } 00372 00373 Set_PU_Info_state(pu, WT_SYMTAB, Subsect_InMem); 00374 00375 return 0; 00376 } /* WN_get_symtab */ 00377 00378 00379 INT 00380 WN_get_strtab (void *handle) 00381 { 00382 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_STRTAB); 00383 if (shdr.offset == 0) 00384 return ERROR_RETURN; 00385 00386 Initialize_Strtab ((char *) handle + shdr.offset, shdr.size); 00387 00388 return 0; 00389 } // WN_get_strtab 00390 00391 00392 /* 00393 * Note: fix_tree is a hot spot for the binary reader, so be very careful 00394 * to make everything as fast as possible. 00395 */ 00396 00397 static INT 00398 fix_tree (WN *node, char *base, Elf64_Word size) 00399 { 00400 OPCODE opcode = (OPCODE) WN_opcode (node); 00401 WN *wn; 00402 00403 #if defined(Is_True_On) || defined(DEBUG_IR) 00404 if (verbose_info) { 00405 printf("opcode %s\n", OPCODE_name(opcode)); 00406 last_node = node; 00407 } 00408 #endif 00409 00410 #ifndef CFE 00411 if (opcode == OPC_REGION) 00412 Set_Max_Region_Id (WN_region_id(node)); 00413 #endif 00414 00415 #if defined(BACK_END) 00416 if (opcode == OPC_ALTENTRY) 00417 Set_PU_has_altentry (Get_Current_PU ()); 00418 00419 /* Count whirl nodes that are useful for Olimit and other stats */ 00420 Count_WN_Opcode (opcode, &PU_WN_BB_Cnt, &PU_WN_Stmt_Cnt); 00421 #endif 00422 00423 if (opcode == OPC_BLOCK) { 00424 wn = WN_first(node); 00425 if (wn == (WN *) -1) { 00426 WN_first(node) = NULL; 00427 WN_last(node) = NULL; 00428 } else { 00429 CONVERT_OFFSET(WN*, wn); 00430 WN_first(node) = wn; 00431 CONVERT_OFFSET(WN*, WN_last(node)); 00432 00433 do { 00434 if (fix_tree (wn, base, size) == ERROR_VALUE) 00435 return ERROR_VALUE; 00436 wn = WN_next(wn); 00437 } while (wn); 00438 } 00439 } else if (!OPCODE_is_leaf(opcode)) { 00440 register INT i, cnt; 00441 register WN **wn_ptr; 00442 00443 cnt = WN_kid_count(node); 00444 wn_ptr = &WN_kid(node, 0); 00445 for (i = 0; i < cnt; i++, wn_ptr++) { 00446 wn = *wn_ptr; 00447 if (wn == (WN *) -1) { 00448 *wn_ptr = NULL; 00449 } else { 00450 CONVERT_OFFSET(WN*, wn); 00451 *wn_ptr = wn; 00452 if (fix_tree (wn, base, size) == ERROR_VALUE) 00453 return ERROR_VALUE; 00454 } 00455 } 00456 } 00457 00458 if (OPCODE_has_next_prev(opcode)) { 00459 wn = WN_prev(node); 00460 if (wn == (WN *) -1) { 00461 WN_prev(node) = NULL; 00462 } else { 00463 CONVERT_OFFSET(WN*, wn); 00464 WN_prev(node) = wn; 00465 } 00466 wn = WN_next(node); 00467 if (wn == (WN *) -1) { 00468 WN_next(node) = NULL; 00469 } else { 00470 CONVERT_OFFSET(WN*, wn); 00471 WN_next(node) = wn; 00472 } 00473 } 00474 00475 /* keep track of the last map ID in each opcode category */ 00476 if (WN_map_id(node) != -1) { 00477 register OPERATOR_MAPCAT category = OPCODE_mapcat(opcode); 00478 register INT32 map_id = WN_map_id(node); 00479 register INT32 *last_id_ptr; 00480 00481 last_id_ptr = &WN_MAP_TAB_Last_ID(Current_Map_Tab, category); 00482 if (map_id > *last_id_ptr) { 00483 *last_id_ptr = map_id; 00484 } 00485 } 00486 00487 return 0; 00488 } /* fix_tree */ 00489 00490 00491 00492 void 00493 Set_Verbose_Info (BOOL val) 00494 { 00495 verbose_info = val; 00496 } 00497 00498 00499 template <class ELF> 00500 INT 00501 check_elf_header (const char* baseaddr, Elf64_Word size, const ELF& tag) 00502 { 00503 typename ELF::Elf_Ehdr* ehdr = (typename ELF::Elf_Ehdr*) baseaddr; 00504 if (ehdr->e_ident[EI_VERSION] != EV_CURRENT || 00505 ehdr->e_version != EV_CURRENT) { 00506 return ERROR_RETURN; 00507 } 00508 if (ehdr->e_type != ET_IR 00509 || ehdr->e_shentsize != sizeof(typename ELF::Elf_Shdr)) { 00510 return ERROR_RETURN; 00511 } 00512 if (Target_ABI != ABI_UNDEF && 00513 // only check if expecting a certain target 00514 ehdr->e_machine != Get_Elf_Target_Machine()) 00515 return ABI_MISMATCH; 00516 BOOL is_64bit; 00517 INT isa; 00518 Config_Target_From_ELF (ehdr->e_flags, &is_64bit, &isa); 00519 if ( ! Set_Target_ABI (is_64bit, isa)) 00520 return ABI_MISMATCH; 00521 if (ehdr->e_shstrndx >= ehdr->e_shnum) { 00522 return ERROR_RETURN; 00523 } 00524 if (ehdr->e_shoff >= size || 00525 ehdr->e_shoff + ehdr->e_shnum * sizeof(typename ELF::Elf_Shdr) > size) { 00526 return ERROR_RETURN; 00527 } 00528 typename ELF::Elf_Shdr* shdr = 00529 (typename ELF::Elf_Shdr *) (baseaddr + ehdr->e_shoff); 00530 if ((long) shdr & (ALIGNOF(typename ELF::Elf_Shdr) - 1)) { 00531 return ERROR_RETURN; 00532 } 00533 return tag.Elf_class(); 00534 } 00535 00536 00537 static INT 00538 check_elf_header (const char *baseaddr, Elf64_Word size) 00539 { 00540 if (size < sizeof(Elf64_Ehdr)) 00541 return ERROR_RETURN; 00542 Elf64_Ehdr* ehdr = (Elf64_Ehdr *) baseaddr; 00543 if (!IS_ELF (*ehdr)) 00544 return ERROR_RETURN; 00545 if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) { 00546 return check_elf_header (baseaddr, size, ELF64()); } 00547 00548 #ifndef __ALWAYS_USE_64BIT_ELF__ 00549 else if (ehdr->e_ident[EI_CLASS] == ELFCLASS32) 00550 return check_elf_header (baseaddr, size, ELF32()); 00551 #endif 00552 else 00553 return ERROR_RETURN; 00554 } /* check_elf_header */ 00555 00556 00557 // Note: file_revision may be changed 00558 template <class ELF> 00559 INT 00560 check_section_headers (char *baseaddr, Elf64_Word size, 00561 char* file_revision, const ELF& tag) 00562 { 00563 typename ELF::Elf_Ehdr* ehdr = (typename ELF::Elf_Ehdr*) baseaddr; 00564 typename ELF::Elf_Shdr* shdr = 00565 (typename ELF::Elf_Shdr*) (baseaddr + ehdr->e_shoff); 00566 00567 errno = ENOEXEC; 00568 00569 if (shdr[ehdr->e_shstrndx].sh_offset >= size || 00570 shdr[ehdr->e_shstrndx].sh_offset + 00571 shdr[ehdr->e_shstrndx].sh_size > size) 00572 return ERROR_RETURN; 00573 00574 char* shstrtab = baseaddr + shdr[ehdr->e_shstrndx].sh_offset; 00575 00576 for (INT i = 1; i < ehdr->e_shnum; i++) { 00577 if (shdr[i].sh_offset >= size || 00578 shdr[i].sh_offset + shdr[i].sh_size > size) 00579 return ERROR_RETURN; 00580 if (shdr[i].sh_name >= shdr[ehdr->e_shstrndx].sh_size) 00581 return ERROR_RETURN; 00582 if (shdr[i].sh_link >= ehdr->e_shnum) 00583 return ERROR_RETURN; 00584 if (shdr[i].sh_addralign & (shdr[i].sh_addralign - 1)) 00585 return ERROR_RETURN; 00586 if (shdr[i].sh_addralign > 1 && 00587 (long)(baseaddr + shdr[i].sh_offset) & ((shdr[i].sh_addralign - 1))) 00588 return ERROR_RETURN; 00589 00590 /* search for and verify the revision string */ 00591 if (shdr[i].sh_type == SHT_PROGBITS && 00592 strcmp (shstrtab + shdr[i].sh_name, ELF_COMMENT) == 0) { 00593 register char *p = baseaddr + shdr[i].sh_offset; 00594 register char *eob = p + shdr[i].sh_size - 1; 00595 register int match = 0; 00596 00597 if (*eob != 0) 00598 /* section not NULL-terminated */ 00599 return ERROR_RETURN; 00600 00601 while (p <= eob) { 00602 if (strncmp ("WHIRL:", p, 6) == 0) { 00603 strcpy (file_revision, p); 00604 if (strcmp (WHIRL_REVISION, p) == 0) { 00605 match = 1; 00606 break; 00607 } 00608 } 00609 p += strlen (p) + 1; 00610 } 00611 00612 if (!match && DEBUG_Ir_Version_Check) 00613 return REVISION_MISMATCH; 00614 } 00615 } 00616 00617 errno = 0; 00618 return 1; 00619 } /* check_section_headers */ 00620 00621 static INT 00622 fix_comp_flags (char *base, Elf64_Word size) 00623 { 00624 register char **argv; 00625 register Elf64_Word argc; 00626 00627 if (sizeof(Elf64_Word) > size) 00628 return ERROR_RETURN; 00629 00630 argc = *((Elf64_Word *) base); 00631 00632 if (sizeof(Elf64_Word) + argc * sizeof(Elf64_Word) > size) 00633 return ERROR_RETURN; 00634 argv = (char **) (base + sizeof(Elf64_Word)); 00635 00636 while (argc--) { 00637 register Elf64_Word offset = *((Elf64_Word *)argv); 00638 00639 if (offset > size) 00640 return ERROR_RETURN; 00641 *argv = base + offset; 00642 argv++; 00643 } 00644 00645 return 0; 00646 } /* fix_comp_flags */ 00647 00648 00649 // Note: 'file_revision' may be changed 00650 INT 00651 WN_massage_input (char *baseaddr, Elf64_Word size, char* file_revision) 00652 { 00653 INT st; 00654 00655 if ((st = check_elf_header (baseaddr, size)) < 0) 00656 return st; 00657 00658 #ifndef __ALWAYS_USE_64BIT_ELF__ 00659 if (st == ELFCLASS32) { 00660 if ((st = check_section_headers (baseaddr, size, file_revision, 00661 ELF32())) <= 0) 00662 return st; 00663 } else 00664 #endif 00665 { 00666 if ((st = check_section_headers (baseaddr, size, file_revision, 00667 ELF64())) <= 0) 00668 return st; 00669 } 00670 00671 return 1; 00672 } /* WN_massage_input */ 00673 00674 00675 // Note: 'file_revision' may be changed 00676 static void * 00677 read_file (const char *filename, off_t* mapped_size, char* file_revision) 00678 { 00679 int fd; 00680 INT st; 00681 struct stat stat_buf; 00682 register char *map_addr; 00683 00684 fd = open (filename, O_RDONLY); 00685 if (fd < 0) 00686 return (void *) ERROR_RETURN; 00687 00688 if (fstat (fd, &stat_buf) != 0) 00689 return (void *) ERROR_RETURN; 00690 00691 map_addr = (char *) mmap (0, stat_buf.st_size, PROT_READ|PROT_WRITE, 00692 MAP_PRIVATE, fd, 0); 00693 if (map_addr == (char *)(ERROR_VALUE)) { 00694 close (fd); 00695 return (void *) ERROR_RETURN; 00696 } 00697 00698 close (fd); 00699 00700 if ((st = WN_massage_input(map_addr, stat_buf.st_size, 00701 file_revision)) <= 0) { 00702 munmap (map_addr, stat_buf.st_size); 00703 return (void *) (st); 00704 } 00705 00706 /* if everything is fine, save the size of the file */ 00707 *mapped_size = stat_buf.st_size; 00708 return map_addr; 00709 00710 } /* read_file */ 00711 00712 00713 Elf64_Word 00714 Get_Elf_Section_Size (void *handle, Elf64_Word type, Elf64_Word info) 00715 { 00716 OFFSET_AND_SIZE shdr = get_section (handle, type, info); 00717 if (shdr.offset == 0) return 0; 00718 return shdr.size; 00719 } 00720 00721 /* 00722 * Specify the name of the WHIRL file for reading. If successful, a handle 00723 * will be returned. If the binary was a different revision than what we 00724 * expected, it returns (void*) REVISION_MISMATCH. 00725 * Otherwise, it returns (void *) READER_ERROR and sets errno. 00726 */ 00727 00728 void * 00729 WN_open_input (const char *filename, off_t *mapped_size) 00730 { 00731 if (filename == 0) { 00732 errno = ENOENT; 00733 return (void *) ERROR_RETURN; 00734 } 00735 00736 errno = 0; 00737 00738 return read_file (filename, mapped_size, file_revision); 00739 00740 } /* WN_open_input */ 00741 00742 00743 /* open a new file, used by the inliner when performing across 00744 * file inlining. Note, mapped file size is not saved in the 00745 * static variable. Note that 'file_revision' may change. 00746 */ 00747 extern void * 00748 WN_inline_open_file(const char* file_name, off_t *mapped_size, 00749 char* file_revision) 00750 { 00751 if (file_name == 0) { 00752 errno = ENOENT; 00753 return (void *) ERROR_RETURN; 00754 } 00755 00756 errno = 0; 00757 00758 return read_file (file_name, mapped_size, file_revision); 00759 00760 } 00761 00762 00763 /* 00764 * Read the PU headers. Returns a pointer to the root of the PU_Info 00765 * tree or -1 on error. Returns the number of PUs through the p_num_PUs 00766 * parameter. 00767 */ 00768 00769 PU_Info * 00770 WN_get_PU_Infos (void *handle, INT32 *p_num_PUs) 00771 { 00772 char *base; 00773 INT32 size; 00774 PU_Info *pu_tree; 00775 00776 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_PU_SECTION); 00777 if (shdr.offset == 0) return (PU_Info *)ERROR_RETURN; 00778 00779 base = (char *) handle + shdr.offset; 00780 size = shdr.size; 00781 00782 pu_tree = Read_PU_Infos (base, size, p_num_PUs); 00783 if (pu_tree == (PU_Info *)ERROR_VALUE) 00784 return (PU_Info *)ERROR_RETURN; 00785 00786 return pu_tree; 00787 } 00788 00789 00790 #ifdef BACK_END 00791 void * 00792 WN_get_section_base (void *handle, INT sect) 00793 { 00794 char *base; 00795 00796 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, sect); 00797 if (shdr.offset == 0) return (void *) ERROR_RETURN; 00798 00799 base = (char *) handle + shdr.offset; 00800 return (void *) base; 00801 } 00802 #endif 00803 00804 00805 /* 00806 * Convert the procedure ST in a PU_Info from an ID number to an 00807 * ST pointer. 00808 */ 00809 00810 ST * 00811 WN_get_proc_sym (PU_Info *pu) 00812 { 00813 Subsect_State st = PU_Info_state(pu, WT_PROC_SYM); 00814 00815 if (st == Subsect_InMem) 00816 return &St_Table[PU_Info_proc_sym(pu)]; 00817 if (st != Subsect_Exists) 00818 return (ST *) ERROR_RETURN; 00819 ST *ps = &St_Table[PU_Info_proc_sym(pu)]; 00820 if (ps == NULL) 00821 return (ST *) ERROR_RETURN; 00822 00823 Set_PU_Info_state(pu, WT_PROC_SYM, Subsect_InMem); 00824 00825 return ps; 00826 } 00827 00828 00829 /* 00830 * Given a handle returned by WN_open_input() and a PU_Info structure, 00831 * this function reads the WHIRL tree for the PU. It returns (WN *)(-1) 00832 * if there is an error. 00833 */ 00834 00835 WN * 00836 WN_get_tree (void *handle, PU_Info *pu) 00837 { 00838 register char *section_base, *tree_base; 00839 register Elf64_Word offset, size; 00840 WN *wn; 00841 Elf64_Word first_node; 00842 Subsect_State st = PU_Info_state(pu, WT_TREE); 00843 00844 if (st == Subsect_InMem) 00845 return PU_Info_tree_ptr(pu); 00846 if (st != Subsect_Exists) 00847 return (WN *) ERROR_RETURN; 00848 00849 offset = PU_Info_subsect_offset(pu, WT_TREE); 00850 size = PU_Info_subsect_size(pu, WT_TREE); 00851 00852 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_PU_SECTION); 00853 if (shdr.offset == 0) return (WN *) ERROR_RETURN; 00854 00855 if (offset + size > shdr.size) { 00856 errno = EINVAL; 00857 return (WN *) ERROR_RETURN; 00858 } 00859 00860 section_base = (char *) handle + shdr.offset; 00861 tree_base = section_base + offset; 00862 00863 /* the offset of the first node is at the beginning of the subsection */ 00864 first_node = *(Elf64_Word *)tree_base; 00865 wn = (WN *) (tree_base + first_node); 00866 00867 #ifndef CFE 00868 Set_Max_Region_Id(0); /* reset max id for pu */ 00869 #endif 00870 00871 /* fix up the pointers in the WNs (Note: this must happen after the map 00872 table is set up because it also updates the map ID info in the 00873 map table */ 00874 00875 Current_Map_Tab = PU_Info_maptab(pu); 00876 if (fix_tree (wn, tree_base, size) == ERROR_VALUE) 00877 return (WN *)ERROR_VALUE; 00878 00879 WN_next(wn) = NULL; 00880 WN_prev(wn) = NULL; 00881 00882 Set_PU_Info_tree_ptr(pu, wn); 00883 Set_PU_Info_state(pu, WT_TREE, Subsect_InMem); 00884 00885 return wn; 00886 } /* WN_get_tree */ 00887 00888 00889 /* 00890 * Given a handle returned by WN_open_input(), this functions returns the 00891 * argc and argv pairs for the command line for compiling the IR. The 00892 * value of argc is returned as function return value and is set to 0 if 00893 * the command line cannot be found (or if it is corrupted). The argv is 00894 * passed as a referenced paramenter as the second argument. 00895 */ 00896 00897 INT 00898 WN_get_flags (void *handle, char ***argv) 00899 { 00900 Elf64_Word argc; 00901 char *baseaddr; 00902 00903 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_COMP_FLAGS); 00904 if (shdr.offset == 0) return 0; 00905 00906 baseaddr = (char *) handle + shdr.offset; 00907 if (fix_comp_flags (baseaddr, shdr.size) == ERROR_VALUE) 00908 return 0; 00909 argc = *((Elf64_Word *) baseaddr); 00910 *argv = (char **) (baseaddr + sizeof(Elf64_Word)); 00911 00912 return argc; 00913 } /* WN_get_flags */ 00914 00915 00916 /* 00917 * Given a handle returned by WN_open_input(), this function 00918 * initializes the debug symbol table (dst) with the data in the file. 00919 * Returns -1 if fails, else the size of the section. 00920 */ 00921 00922 INT 00923 WN_get_dst (void *handle) 00924 { 00925 register INT size, num_blocks; 00926 char *base, *ptr, *blk; 00927 DST_BLOCK_IDX j; 00928 00929 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_DST); 00930 if (shdr.offset == 0) return ERROR_RETURN; 00931 00932 base = (char *) handle + shdr.offset; 00933 size = shdr.size; 00934 00935 /* sections contains data, then array of block_headers, then num_blocks. */ 00936 ptr = base + size - sizeof(mINT32); 00937 num_blocks = *(INT32*) ptr; 00938 num_blocks++; /* last_block_number + 1 == number of blocks */ 00939 ptr -= (num_blocks * sizeof(block_header)); 00940 00941 DST_Init (ptr, num_blocks); 00942 FOREACH_DST_BLOCK(j) { 00943 blk = ((DST_Type *)Current_DST)->dst_blocks[j].offset; 00944 if (blk == (char *)-1) { 00945 ((DST_Type *)Current_DST)->dst_blocks[j].offset = NULL; 00946 } else { 00947 CONVERT_OFFSET(char*, blk); 00948 ((DST_Type *)Current_DST)->dst_blocks[j].offset = blk; 00949 } 00950 } 00951 00952 return size; 00953 } /* WN_get_dst */ 00954 00955 00956 #if defined(BACK_END) || defined(IR_TOOLS) 00957 // read the feedback info, if any 00958 INT 00959 WN_get_feedback (void* handle, PU_Info* pu, MEM_POOL* pool) 00960 { 00961 Subsect_State st = PU_Info_state(pu, WT_FEEDBACK); 00962 00963 switch (st) { 00964 case Subsect_Missing: 00965 case Subsect_InMem: 00966 default: 00967 return 0; 00968 case Subsect_Exists: 00969 break; 00970 case Subsect_Written: 00971 return ERROR_RETURN; 00972 } 00973 00974 Elf64_Word offset = PU_Info_subsect_offset (pu, WT_FEEDBACK); 00975 Elf64_Word size = PU_Info_subsect_size (pu, WT_FEEDBACK); 00976 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_PU_SECTION); 00977 if (shdr.offset == 0) 00978 return ERROR_RETURN; 00979 00980 if (offset + size >= shdr.size) { 00981 errno = EINVAL; 00982 return ERROR_RETURN; 00983 } 00984 00985 INTPTR baseaddr = (INTPTR)handle + shdr.offset + offset; 00986 00987 Set_PU_Info_feedback_ptr (pu, baseaddr); 00988 Set_PU_Info_state (pu, WT_FEEDBACK, Subsect_InMem); 00989 00990 return 0; 00991 } // WN_get_feedback 00992 #endif 00993 00994 00995 00996 #if defined(BACK_END) || defined(BUILD_WNPREFETCH) 00997 /* Read the prefetch pointer mapping */ 00998 INT 00999 WN_get_prefetch (void *handle, PU_Info *pu) 01000 { 01001 Elf64_Word offset, size; 01002 char *cur_addr, *end_addr, *tree_base; 01003 Elf64_Word node_offset; 01004 WN *node; 01005 PF_POINTER *pf_ptr; 01006 Subsect_State st = PU_Info_state(pu, WT_PREFETCH); 01007 Current_Map_Tab = PU_Info_maptab(pu); 01008 01009 if (st == Subsect_Written) 01010 return ERROR_RETURN; 01011 if (st != Subsect_Exists) 01012 return 0; 01013 01014 offset = PU_Info_subsect_offset(pu, WT_PREFETCH); 01015 size = PU_Info_subsect_size(pu, WT_PREFETCH); 01016 01017 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_PU_SECTION); 01018 if (shdr.offset == 0) return ERROR_RETURN; 01019 01020 if (offset + size >= shdr.size) { 01021 errno = EINVAL; 01022 return ERROR_RETURN; 01023 } 01024 01025 /* find the start of the tree subsection */ 01026 tree_base = (char *) handle + shdr.offset + 01027 PU_Info_subsect_offset(pu, WT_TREE); 01028 01029 cur_addr = (char *)handle + shdr.offset + offset; 01030 end_addr = cur_addr + size; 01031 01032 for (;;) { 01033 node_offset = *(Elf64_Word *)cur_addr; 01034 cur_addr += (sizeof(Elf64_Word)); 01035 01036 if (node_offset == (Elf64_Word)-1) break; 01037 01038 cur_addr = (char *)ir_b_align((off_t)cur_addr, ALIGNOF(PF_POINTER), 01039 0); 01040 pf_ptr = (PF_POINTER *)cur_addr; 01041 cur_addr += (sizeof(PF_POINTER)); 01042 01043 /* fixup the WN pointers. If -1 then store NULL */ 01044 node = (WN *)(tree_base + node_offset); 01045 if (pf_ptr->wn_pref_1L == (WN*) -1) { 01046 pf_ptr->wn_pref_1L = NULL; 01047 } else { 01048 pf_ptr->wn_pref_1L = 01049 (WN*)(tree_base + (INTPTR)pf_ptr->wn_pref_1L); 01050 } 01051 01052 if (pf_ptr->wn_pref_2L == (WN*) -1) { 01053 pf_ptr->wn_pref_2L = NULL; 01054 } else { 01055 pf_ptr->wn_pref_2L = 01056 (WN*)(tree_base + (INTPTR)pf_ptr->wn_pref_2L); 01057 } 01058 01059 /* add the pointer to the prefetch mapping */ 01060 WN_MAP_Set(WN_MAP_PREFETCH, node, (void *)pf_ptr); 01061 01062 if (cur_addr > end_addr) return ERROR_RETURN; 01063 } 01064 01065 PU_Info_subsect_ptr(pu, WT_PREFETCH) = NULL; 01066 Set_PU_Info_state(pu, WT_PREFETCH, Subsect_InMem); 01067 01068 return 0; 01069 } /* WN_get_prefetch */ 01070 01071 #endif /* BACK_END || BUILD_WNPREFETCH */ 01072 01073 static inline void 01074 WN_MAP_put(WN_MAP wn_map, WN *wn, INT32 value) 01075 { 01076 WN_MAP32_Set(wn_map, wn, value); 01077 } 01078 01079 static inline void 01080 WN_MAP_put(WN_MAP wn_map, WN *wn, INT64 value) 01081 { 01082 WN_MAP64_Set(wn_map, wn, value); 01083 } 01084 01085 static inline void 01086 WN_MAP_put(WN_MAP wn_map, WN *wn, void *value) 01087 { 01088 WN_MAP_Set(wn_map, wn, value); 01089 } 01090 01091 template<class MAP_ENTRY_TYPE> 01092 static inline INT 01093 WN_read_generic_map(void *handle, 01094 PU_Info *pu, 01095 INT32 subsection_type, 01096 WN_MAP value_map, 01097 MAP_ENTRY_TYPE) 01098 { 01099 Subsect_State state = PU_Info_state (pu, subsection_type); 01100 Elf64_Word offset, size; 01101 char *cur_addr, *end_addr, *tree_base; 01102 01103 if (state == Subsect_Written) { 01104 return ERROR_RETURN; 01105 } 01106 if (state != Subsect_Exists) { 01107 return 0; 01108 } 01109 01110 OFFSET_AND_SIZE shdr = get_section (handle, SHT_MIPS_WHIRL, WT_PU_SECTION); 01111 if (shdr.offset == 0) { 01112 return ERROR_RETURN; 01113 } 01114 01115 offset = PU_Info_subsect_offset(pu, subsection_type); 01116 size = PU_Info_subsect_size(pu, subsection_type); 01117 01118 if (offset + size >= shdr.size) { 01119 errno = EINVAL; 01120 return ERROR_RETURN; 01121 } 01122 01123 /* find the start of the tree subsection */ 01124 tree_base = (char *) handle + shdr.offset + 01125 PU_Info_subsect_offset(pu, WT_TREE); 01126 01127 cur_addr = (char *)handle + shdr.offset + offset; 01128 end_addr = cur_addr + size; 01129 01130 for (;;) { 01131 MAP_ENTRY_TYPE map_value; 01132 Elf64_Word node_offset = *(Elf64_Word *) cur_addr; 01133 WN *node; 01134 01135 cur_addr += (sizeof(Elf64_Word)); // advance over WN offset 01136 01137 if (node_offset == (Elf64_Word)-1) 01138 break; 01139 01140 // Why do we align here but not for the WN offset? -- RK 980615 01141 cur_addr = (char *) ir_b_align ((off_t) cur_addr, 01142 sizeof(MAP_ENTRY_TYPE), 01143 0); 01144 map_value = * (MAP_ENTRY_TYPE *) cur_addr; 01145 cur_addr += sizeof(MAP_ENTRY_TYPE); // advance over map entry 01146 01147 node = (WN *) (tree_base + node_offset); 01148 01149 // TODO: The following must be made generic. 01150 /* add the value to the WHIRL map in memory */ 01151 WN_MAP_put(value_map, node, map_value); 01152 01153 if (cur_addr > end_addr) 01154 return ERROR_RETURN; 01155 } 01156 01157 PU_Info_subsect_ptr(pu, subsection_type) = NULL; 01158 Set_PU_Info_state(pu, subsection_type, Subsect_InMem); 01159 01160 return 0; 01161 } 01162 01163 INT 01164 WN_get_INT32_map(void *handle, 01165 PU_Info *pu, 01166 INT32 subsection_type, 01167 WN_MAP value_map) 01168 { 01169 return WN_read_generic_map(handle, pu, subsection_type, 01170 value_map, (INT32) 0); 01171 } 01172 01173 INT 01174 WN_get_voidptr_map(void *handle, 01175 PU_Info *pu, 01176 INT32 subsection_type, 01177 WN_MAP value_map) 01178 { 01179 return WN_read_generic_map(handle, pu, subsection_type, 01180 value_map, (void *) 0); 01181 } 01182 01183 01184 01185 /* 01186 * Given a handle returned by WN_open_input(), this function releases all 01187 * the memory used for reading the WHIRL file. Note that previously 01188 * pointers returned by WN_get_tree() will no longer be valid. 01189 */ 01190 01191 void 01192 WN_free_input (void *handle, off_t mapped_size) 01193 { 01194 if (handle == 0 || handle == (void *)(-1)) 01195 return; 01196 01197 // Solaris CC, against UNIX standard, wants first arg to be char*. 01198 munmap ((char*)handle, mapped_size); 01199 } /* WN_free_input */ 01200 01201 01202 #ifndef OWN_ERROR_PACKAGE 01203 /* 01204 * Define common routines for reading all the whirl sections. 01205 * These routines use the standard compiler error reporting mechanism. 01206 */ 01207 01208 static void *global_fhandle; /* file handle */ 01209 static void *local_fhandle; /* file handle */ 01210 static const char *global_ir_file; /* name of ir input file */ 01211 static const char *local_ir_file; /* name of ir input file */ 01212 01213 static void 01214 open_specified_input (const char *input_file, const char **ir_input, 01215 void **fhandle, off_t *mapped_size) 01216 { 01217 Set_Error_Phase ( "Reading WHIRL file" ); 01218 *ir_input = input_file; 01219 *fhandle = WN_open_input (input_file, mapped_size); 01220 01221 if (*fhandle == (void*) REVISION_MISMATCH) { 01222 ErrMsg ( EC_IR_Revision, file_revision, *ir_input); 01223 } else if (*fhandle == (void*) ABI_MISMATCH) { 01224 ErrMsg ( EC_IR_Revision, 01225 "abi of whirl file doesn't match abi from command-line", 01226 *ir_input); 01227 } else if (*fhandle == (void*) READER_ERROR) { 01228 ErrMsg ( EC_IR_Open, *ir_input, errno ); 01229 } 01230 } 01231 01232 // same ir file for both global and local 01233 void * 01234 Open_Input_Info (const char *input_file) 01235 { 01236 open_specified_input (input_file, 01237 &global_ir_file, &global_fhandle, &global_mapped_size); 01238 local_ir_file = global_ir_file; 01239 local_fhandle = global_fhandle; 01240 local_mapped_size = global_mapped_size; 01241 return global_fhandle; 01242 } 01243 01244 void * 01245 Open_Global_Input (const char *input_file) 01246 { 01247 open_specified_input (input_file, 01248 &global_ir_file, &global_fhandle, &global_mapped_size); 01249 return global_fhandle; 01250 } 01251 01252 void * 01253 Open_Local_Input (const char *input_file) 01254 { 01255 open_specified_input (input_file, 01256 &local_ir_file, &local_fhandle, &local_mapped_size); 01257 return local_fhandle; 01258 } 01259 01260 /* 01261 * Read all the global tables and the PU section header. Returns a 01262 * pointer to the PU_Info tree. If "p_num_PUs" is non-NULL, the number 01263 * of PUs is returned through it. 01264 */ 01265 01266 PU_Info * 01267 Read_Global_Info (INT32 *p_num_PUs) 01268 { 01269 PU_Info *pu_tree; 01270 01271 Set_Error_Phase ( "Reading WHIRL file" ); 01272 01273 if (WN_get_strtab(global_fhandle) == -1) { 01274 ErrMsg ( EC_IR_Scn_Read, "strtab", global_ir_file); 01275 } 01276 01277 if ((INT) WN_get_global_symtab (global_fhandle) == -1) { 01278 ErrMsg ( EC_IR_Scn_Read, "global symtab", global_ir_file); 01279 } 01280 01281 01282 // for now, get dst from local file (later change to global) 01283 if (WN_get_dst(local_fhandle) == -1) { 01284 ErrMsg ( EC_IR_Scn_Read, "dst", local_ir_file); 01285 } 01286 01287 // PU_Info is stored in local file 01288 pu_tree = WN_get_PU_Infos (local_fhandle, p_num_PUs); 01289 if (pu_tree == (PU_Info *)-1) { 01290 ErrMsg ( EC_IR_Scn_Read, "PU headers", local_ir_file); 01291 } 01292 if (verbose_info) { 01293 printf("done reading global info\n"); 01294 } 01295 01296 return pu_tree; 01297 } 01298 01299 01300 void 01301 Read_Local_Info (MEM_POOL *pool, PU_Info *pu) 01302 { 01303 const char *save_phase = Get_Error_Phase(); 01304 Set_Error_Phase ( "Reading WHIRL file" ); 01305 01306 /* set the map table */ 01307 Current_Map_Tab = PU_Info_maptab(pu); 01308 if (!Current_Map_Tab) { 01309 Current_Map_Tab = WN_MAP_TAB_Create(pool); 01310 PU_Info_maptab(pu) = Current_Map_Tab; 01311 } 01312 01313 CURRENT_SYMTAB = PU_lexical_level (&St_Table[PU_Info_proc_sym (pu)]); 01314 New_Scope (CURRENT_SYMTAB, MEM_pu_nz_pool_ptr, FALSE); 01315 01316 if (WN_get_symtab (local_fhandle, pu) == -1) 01317 ErrMsg ( EC_IR_Scn_Read, "local symtab", local_ir_file); 01318 01319 Scope_tab[CURRENT_SYMTAB].st = WN_get_proc_sym (pu); 01320 if (Scope_tab[CURRENT_SYMTAB].st == (ST *) -1) 01321 ErrMsg ( EC_IR_Scn_Read, "proc ST", local_ir_file); 01322 else 01323 Current_pu = &Pu_Table[ST_pu (Scope_tab[CURRENT_SYMTAB].st)]; 01324 01325 01326 if (WN_get_tree (local_fhandle, pu) == (WN*) -1) { 01327 ErrMsg ( EC_IR_Scn_Read, "tree", local_ir_file); 01328 } 01329 01330 #if defined(BACK_END) || defined(BUILD_WNPREFETCH) 01331 if (WN_get_prefetch (local_fhandle, pu) == -1) { 01332 ErrMsg ( EC_IR_Scn_Read, "prefetch map", local_ir_file); 01333 } 01334 #endif 01335 01336 01337 if (WN_get_INT32_map(local_fhandle, pu, 01338 WT_ALIAS_CLASS, WN_MAP_ALIAS_CLASS) == -1) { 01339 ErrMsg ( EC_IR_Scn_Read, "alias class map", local_ir_file); 01340 } 01341 01342 if (WN_get_voidptr_map(local_fhandle, pu, 01343 WT_AC_INTERNAL, WN_MAP_AC_INTERNAL) == -1) { 01344 ErrMsg ( EC_IR_Scn_Read, "alias class internal map", local_ir_file); 01345 } 01346 01347 Set_Error_Phase(save_phase); 01348 } 01349 01350 01351 void 01352 Free_Local_Info (PU_Info *pu) 01353 { 01354 Delete_Scope (PU_lexical_level (&St_Table[PU_Info_proc_sym (pu)])); 01355 01356 /* deallocate the old map table */ 01357 if (PU_Info_maptab(pu)) { 01358 WN_MAP_TAB_Delete(PU_Info_maptab(pu)); 01359 PU_Info_maptab(pu) = NULL; 01360 } 01361 } 01362 01363 void 01364 Free_Local_Input(void) 01365 { 01366 WN_free_input(local_fhandle, local_mapped_size); 01367 local_fhandle = 0; 01368 } 01369 01370 void 01371 Free_Input_Info (void) 01372 { 01373 WN_free_input(global_fhandle, global_mapped_size); 01374 if (global_fhandle != local_fhandle) { 01375 Free_Local_Input(); 01376 } 01377 global_fhandle = 0; 01378 } 01379 01380 #endif /* OWN_ERROR_PACKAGE */ 01381