Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
ir_bread.cxx
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 #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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines