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