Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
pu_info.cxx
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 /*
00037  * This file contains the routines to read and write the PU_Info
00038  * headers.  The current file format for the headers is:
00039  *
00040  *      version number
00041  *      number of PUs (num_PUs)
00042  *      array [num_PUs] of {
00043  *          proc ST id
00044  *          flags
00045  *          DST index
00046  *          array index of previous PU_Info (or -1 if this is a child)
00047  *      }
00048  *      number of subsection kinds (scn_kinds)
00049  *      array [scn_kinds] of {
00050  *          subsection kind identifier
00051  *          array [num_PUs] of {
00052  *              subsection offset
00053  *              subsection size
00054  *          }
00055  *      }
00056  */
00057 
00058 #ifdef USE_PCH
00059 #include "common_com_pch.h"
00060 #endif /* USE_PCH */
00061 #pragma hdrstop
00062 
00063 #include <elf.h>
00064 #include <string.h> /* for memset() */
00065 #include "cxx_memory.h"
00066 #include "defs.h"
00067 #include "symtab.h"
00068 #include "pu_info.h"
00069 
00070 PU_Info *Current_PU_Info = NULL;
00071 
00072 void
00073 PU_Info_init (PU_Info *pu)
00074 {
00075     pu->state = 0;
00076     PU_Info_next(pu) = NULL;
00077     PU_Info_child(pu) = NULL;
00078     PU_Info_proc_id(pu) = 0;
00079     PU_Info_flags(pu) = 0;
00080     PU_Info_pu_dst(pu) = DST_INVALID_IDX;
00081     PU_Info_cu_dst(pu) = DST_INVALID_IDX;
00082     PU_Info_maptab(pu) = NULL;
00083 }
00084 
00085 
00086 static INT number_PU_Infos(PU_Info *pu_tree, INT num_PUs);
00087 
00088 INT
00089 Sizeof_PU_Infos (PU_Info *pu_tree)
00090 {
00091     INT32 hdr_sz, num_PUs;
00092 
00093     /* count the number of PUs */
00094     num_PUs = number_PU_Infos(pu_tree, 0);
00095 
00096     /* calculate the header size:
00097        . 3 INT32s                               version, PU & subsection cnts
00098        . WT_SUBSECTIONS INT32s                  subsection kind identifiers
00099        . num_PUs * 3 INT32s                     proc ST IDs, flags, prev index
00100        . num_PUs * DST_IDXs                     DST indices
00101        . num_PUs * WT_SUBSECTIONS Elf64_Words   subsection offsets
00102        . num_PUs * WT_SUBSECTIONS Elf64_Words   subsection sizes
00103        (factor out the constants so it can be folded to X + num_PUs * Y) */
00104 
00105     hdr_sz = (sizeof(mINT32) * (3 + WT_SUBSECTIONS)) +
00106         num_PUs * ((3 * sizeof(mINT32)) + sizeof(DST_IDX) +
00107                    (2 * sizeof(Elf64_Word) * WT_SUBSECTIONS));
00108 
00109     return hdr_sz;
00110 }
00111 
00112 
00113 INT
00114 number_PU_Infos (PU_Info *pu_tree, INT num_PUs)
00115 {
00116     PU_Info *pu;
00117     for (pu = pu_tree; pu; pu = PU_Info_next(pu)) {
00118 
00119         /* stash the array index in the map table field */
00120         PU_Info_maptab(pu) = (struct wn_map_tab *)num_PUs;
00121 
00122         num_PUs += 1;
00123 
00124         if (PU_Info_child(pu)) {
00125             num_PUs = number_PU_Infos(PU_Info_child(pu), num_PUs);
00126         }
00127     }
00128     return num_PUs;
00129 }
00130 
00131 
00132 /*
00133  * This procedure writes the tree of PU_Infos to the address specified
00134  * in the base parameter.  Note that unlike Read_PU_Infos, the base
00135  * address here refers to the actual address where the header will be
00136  * written, not the beginning of the WT_PU_SECTION.  If no errors occur,
00137  * the procedure returns 0; otherwise -1.
00138  */
00139 
00140 static char *write_PU_fields(PU_Info *pu_tree, char *addr, INT32 *p_num_PUs);
00141 static char *write_PU_subsect_info(PU_Info *pu_tree, INT32 k, char *addr);
00142 
00143 INT
00144 Write_PU_Infos (PU_Info *pu_tree, char *base)
00145 {
00146     INT32 k, num_PUs = 0;
00147     char *addr;
00148 
00149     /* write the version number */
00150     *(INT32 *)base = PU_HEADER_VERSION;
00151     base += sizeof(mINT32);
00152 
00153     /* leave space for the number of PUs */
00154     addr = base + sizeof(mINT32);
00155 
00156     addr = write_PU_fields(pu_tree, addr, &num_PUs);
00157 
00158     /* write out the number of subsection kinds */
00159     *(INT32 *)addr = WT_SUBSECTIONS;
00160     addr += sizeof(mINT32);
00161 
00162     for (k = 0; k < WT_SUBSECTIONS; k++) {
00163 
00164         /* write out the subsection identifier */
00165         *(INT32 *)addr = k;
00166         addr += sizeof(mINT32);
00167 
00168         addr = write_PU_subsect_info(pu_tree, k, addr);
00169         if (!addr) return -1;
00170     }
00171 
00172     /* write out the number of PUs */
00173     *(INT32 *)base = num_PUs;
00174 
00175     return 0;
00176 }
00177 
00178 
00179 char *
00180 write_PU_fields (PU_Info *pu_tree, char *addr, INT32 *p_num_PUs)
00181 {
00182     PU_Info *pu, *prev_pu = NULL;
00183     for (pu = pu_tree; pu; pu = PU_Info_next(pu)) {
00184 
00185         /* write out the proc ST IDs */
00186         *(INT32 *)addr = (INT32) PU_Info_proc_sym(pu);
00187         addr += sizeof(mINT32);
00188 
00189         /* write the flags */
00190         *(INT32 *)addr = PU_Info_flags(pu);
00191         addr += sizeof(mINT32);
00192 
00193         /* write the DST index */
00194         *(DST_IDX *)addr = PU_Info_pu_dst(pu);
00195         addr += sizeof(DST_IDX);
00196 
00197         /* write the array index of the previous PU_Info or -1 if this
00198            is the first child of the immediately preceding PU_Info */
00199         if (prev_pu) {
00200             *(INT32 *)addr = (INT32) (INTPS) PU_Info_maptab(prev_pu);
00201         } else {
00202             *(INT32 *)addr = -1;
00203         }
00204         addr += sizeof(mINT32);
00205 
00206         *p_num_PUs += 1;
00207 
00208         if (PU_Info_child(pu)) {
00209             addr = write_PU_fields(PU_Info_child(pu), addr, p_num_PUs);
00210         }
00211 
00212         prev_pu = pu;
00213     }
00214     return addr;
00215 }
00216 
00217 
00218 char *
00219 write_PU_subsect_info (PU_Info *pu_tree, INT32 k, char *addr)
00220 {
00221     PU_Info *pu;
00222     for (pu = pu_tree; pu; pu = PU_Info_next(pu)) {
00223 
00224         if (PU_Info_state(pu, k) == Subsect_Missing) {
00225             PU_Info_subsect_offset(pu, k) = 0;
00226             PU_Info_subsect_size(pu, k) = 0;
00227         } else if (PU_Info_state(pu, k) != Subsect_Written) {
00228             return NULL;
00229         }
00230 
00231         /* write out the subsection offset and size */
00232         *(Elf64_Word *)addr = PU_Info_subsect_offset(pu, k);
00233         addr += sizeof(Elf64_Word);
00234         *(Elf64_Word *)addr = PU_Info_subsect_size(pu, k);
00235         addr += sizeof(Elf64_Word);
00236 
00237         if (PU_Info_child(pu)) {
00238             addr = write_PU_subsect_info(PU_Info_child(pu), k, addr);
00239             if (!addr) return NULL;
00240         }
00241     }
00242     return addr;
00243 }
00244 
00245 
00246 /*
00247  * Given a pointer to the beginning of the WT_PU_SECTION and the section
00248  * size, this function reads the PU headers into a tree of PU_Info structures.
00249  * It returns a pointer to the root of the tree and returns the number of
00250  * PUs through the p_num_PUs parameter.  The return value is -1 if an
00251  * error occurs.
00252  */
00253 
00254 PU_Info *
00255 Read_PU_Infos (char *base, INT32 size, INT32 *p_num_PUs)
00256 {
00257     INT n, k;
00258     char *addr;
00259     INT32 version_num, num_PUs, prev_index, subsect_kinds, kind;
00260     PU_Info *pu_array, *pu;
00261     Elf64_Word hdr_offset;
00262 
00263     hdr_offset = *(Elf64_Word *)base;
00264     addr = base + hdr_offset;
00265 
00266     /* check the version number */
00267     version_num = *(INT32 *)addr;
00268     addr += sizeof(mINT32);
00269     if (version_num != PU_HEADER_VERSION) {
00270         return (PU_Info *)-1;
00271     }
00272 
00273     num_PUs = *(INT32 *)addr;
00274     addr += sizeof(mINT32);
00275 
00276     if (p_num_PUs) *p_num_PUs = num_PUs;
00277     if (num_PUs < 0) {
00278         return (PU_Info *)-1;
00279     }
00280     if (num_PUs == 0) {
00281         return NULL;
00282     }
00283 
00284     pu_array = (PU_Info *)malloc(sizeof(PU_Info) * num_PUs);
00285 
00286     memset(pu_array, '\0', sizeof(PU_Info) * num_PUs);
00287 
00288     for (n = 0, pu = pu_array; n < num_PUs; n++, pu++) {
00289         /* initialize */
00290         PU_Info_init(pu);
00291 
00292         /* read the procedure ST IDs */
00293         Set_PU_Info_state(pu, WT_PROC_SYM, Subsect_Exists);
00294         PU_Info_proc_id(pu) = *(INT32 *)addr;
00295         addr += sizeof(mINT32);
00296 
00297         /* read the flags */
00298         PU_Info_flags(pu) = *(INT32 *)addr;
00299         addr += sizeof(mINT32);
00300 
00301         /* read the DST_IDX */
00302         PU_Info_pu_dst(pu) = *(DST_IDX *)addr;
00303         addr += sizeof(DST_IDX);
00304 
00305         /* link up the PU_Infos */
00306         prev_index = *(INT32 *)addr;
00307         addr += sizeof(mINT32);
00308         if (prev_index == -1) {
00309             if (n != 0) PU_Info_child(&pu_array[n-1]) = pu;
00310         } else {
00311             PU_Info_next(&pu_array[prev_index]) = pu;
00312         }
00313     }
00314 
00315     subsect_kinds = *(INT32 *)addr;
00316     addr += sizeof(mINT32);
00317 
00318     for (k = 0; k < subsect_kinds; k++) {
00319 
00320         /* read the subsection kind identifier */
00321         kind = *(INT32 *)addr;
00322         addr += sizeof(mINT32);
00323 
00324         /* ignore things we don't understand */
00325         if (kind >= WT_SUBSECTIONS) {
00326             addr += (num_PUs * 2 * sizeof(Elf64_Word));
00327             continue;
00328         }
00329 
00330         for (n = 0, pu = pu_array; n < num_PUs; n++, pu++) {
00331             /* read the offset and size of the subsection */
00332             PU_Info_subsect_offset(pu, kind) = *(Elf64_Word *)addr;
00333             addr += sizeof(Elf64_Word);
00334             PU_Info_subsect_size(pu, kind) = *(Elf64_Word *)addr;
00335             addr += sizeof(Elf64_Word);
00336 
00337             if (PU_Info_subsect_size(pu, kind) != 0) {
00338                 Set_PU_Info_state(pu, kind, Subsect_Exists);
00339             }
00340         }
00341     }
00342 
00343     /* make sure we didn't run off the end of the header */
00344     if (addr > base + size) return (PU_Info *)-1;
00345 
00346     return pu_array;
00347 }
00348 
00349   // assertion-checking data structure for Save_Local_Symtab()/
00350   // Restore_Local_Symtab()
00351 struct SAVED_SCOPE {
00352   enum {
00353     MAGIC = 0x23456789
00354   };
00355   INT32 magic;
00356   ST *parent_pu_st;
00357   SCOPE *saved_scope;
00358 
00359   SAVED_SCOPE(SCOPE *sc, SYMTAB_IDX level) :
00360       magic(MAGIC), parent_pu_st(Scope_tab[level - 1].st), saved_scope(sc)
00361     { }
00362 
00363     // get saved scope, with extensive assertion checking
00364   SCOPE *Get_Scope(SYMTAB_IDX level) {
00365     if (magic != MAGIC)
00366       Fail_FmtAssertion("bad SAVED_SCOPE magic number");
00367     if (Scope_tab[level - 1].st != parent_pu_st)
00368       Fail_FmtAssertion("parent PU ST mismatch between save and restore");
00369 
00370     return saved_scope;
00371   }
00372 };
00373 
00374 
00375 // make a copy of the specified entry of Scope_tab, so that it can be later 
00376 // restored by Restore_Local_Symtab.  This is primarily used by the
00377 // mp-lowerer where multiple nested procedures are created before they are
00378 // compiled. We need a place holder for their corresponding tree nodes and
00379 // local symtab.  Note that the Scope_tab entry will be re-initialized for
00380 // the next nested procedure.
00381 void
00382 Save_Local_Symtab (SYMTAB_IDX level, PU_Info *pu)
00383 {
00384     // Why all this assertion checking?  Because this way of saving/
00385     // restoring scopes is a hack that the symbol table and PU_Info
00386     // classes weren't really designed to support, so this could easily
00387     // break if it's used in an unexpected way.
00388   FmtAssert (PU_Info_state (pu, WT_SYMTAB) == Subsect_InMem,
00389              ("Local symbol table not in memory"));
00390   FmtAssert (level >= 2,
00391              ("saving symtab at too high a level (%d)", level));
00392   FmtAssert (Current_scope >= level, ("bad level and/or Current_scope"));
00393 
00394     // to make sure that save/restore symtab hack is used only by those
00395     // who understand it, the caller must set symtab_ptr to NULL
00396   FmtAssert (PU_Info_symtab_ptr(pu) == NULL,  
00397              ("Incorrect call to Save_Local_Symtab"));
00398   FmtAssert (level == PU_lexical_level (&St_Table[PU_Info_proc_sym (pu)]),
00399              ("Invalid pu_info in Save_Local_Symtab"));
00400 
00401   SCOPE *scope = (SCOPE*) MEM_POOL_Alloc (Scope_tab[CURRENT_SYMTAB].pool,
00402                                           sizeof(SCOPE));
00403   *scope = Scope_tab[level];
00404   SAVED_SCOPE *saved_scope = CXX_NEW(SAVED_SCOPE(scope, level),
00405                                      Scope_tab[CURRENT_SYMTAB].pool);
00406 
00407   Set_PU_Info_symtab_ptr (pu, saved_scope);
00408 } // Save_Local_Symtab
00409 
00410 
00411 void
00412 Restore_Local_Symtab (PU_Info *pu)
00413 {
00414     FmtAssert (PU_Info_state (pu, WT_SYMTAB) == Subsect_InMem,
00415                ("Local symbol table not in memory"));
00416 
00417     FmtAssert (PU_Info_symtab_ptr(pu),
00418                ("Incorrect call to Save/Restore_Local_Symtab pair"));
00419 
00420     SYMTAB_IDX level = PU_lexical_level (&St_Table[PU_Info_proc_sym (pu)]);
00421 
00422     FmtAssert(Current_scope >= level, ("bad level and/or Current_scope"));
00423 
00424     SAVED_SCOPE *saved_scope = (SAVED_SCOPE *) PU_Info_symtab_ptr(pu);
00425 
00426     Scope_tab[level] = *saved_scope->Get_Scope(level);
00427 
00428 } // Restore_Local_Symtab
00429 
00430 
00431 #ifdef Is_True_On
00432 /* Names of subsections for fdump_PU_Info_state()
00433  */
00434 static char *PU_Info_subsect_name[WT_SUBSECTIONS] = {
00435   "WT_SYMTAB",
00436   "WT_TREE",
00437   "WT_DEPGRAPH",
00438   "WT_PREFETCH",
00439   "WT_REGIONS",
00440   "WT_FEEDBACK",
00441   "WT_FREQ",
00442   "WT_AC_INTERNAL",
00443   "WT_ALIAS_CLASS"
00444 };
00445 
00446 void fdump_PU_Info_state(FILE *f, PU_Info *pu_info)
00447 {
00448   INT i;
00449 
00450   /* For each subsection, show the state of the subsection. */
00451   for (i = WT_PROC_SYM; i < WT_SUBSECTIONS; i++) {
00452     /* WT_PROC_SYM is special; it is -1. */
00453     if (i == WT_PROC_SYM) {
00454       (void) fprintf(f, "WT_PROC_SYM: ");
00455     }
00456     else {
00457       (void) fprintf(f, "%s: ", PU_Info_subsect_name[i]);
00458     }
00459     switch (PU_Info_state(pu_info, i)) {
00460     case Subsect_Missing:
00461       (void) fprintf(f, "Subsect_Missing\n");
00462       break;
00463     case Subsect_Exists:
00464       (void) fprintf(f, "Subsect_Exists\n");
00465       break;
00466     case Subsect_InMem:
00467       (void) fprintf(f, "Subsect_InMem\n");
00468       break;
00469     case Subsect_Written:
00470       (void) fprintf(f, "Subsect_Written\n");
00471       break;
00472     default:
00473       (void) fprintf(f, "Unknown state\n");
00474       break;
00475     }
00476   }
00477 }
00478 
00479 void dump_PU_Info_state(PU_Info *pu_info)
00480 {
00481   fdump_PU_Info_state(stdout, pu_info);
00482 }
00483 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines