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 unlink() */ 00040 #include <fcntl.h> /* for open() */ 00041 #include <sys/mman.h> /* for mmap() */ 00042 #include <alloca.h> /* for alloca() */ 00043 #include <signal.h> /* for signal() */ 00044 #include <string.h> /* for strerror() */ 00045 #include <errno.h> /* for system error code */ 00046 #include <elf.h> /* Open64 version */ 00047 #include <sys/elf_whirl.h> /* for WHIRL sections' sh_info */ 00048 #include <cmplrs/rcodes.h> 00049 00050 #include "x_stdlib.h" // for mkstemp() 00051 00052 #ifndef USE_STANDARD_TYPES 00053 # define USE_STANDARD_TYPES /* override unwanted defines in "defs.h" */ 00054 #endif 00055 00056 #include "defs.h" /* for wn_core.h */ 00057 #include "alignof.h" /* for ALIGNOF() */ 00058 #ifdef OWN_ERROR_PACKAGE 00059 /* Turn off assertion in the opcode handling routines, we assume the tree 00060 * is clean. Also, this removes the dependency on "errors.h", which is not 00061 * used by all programs. 00062 */ 00063 #define Is_True(x,y) (0) 00064 #define ERRORS_INCLUDED 00065 #else 00066 #include "erglob.h" 00067 #endif 00068 #include "errors.h" 00069 #include "opcode.h" /* for wn_core.h */ 00070 #include "mempool.h" /* for MEM_POOL (for maps) */ 00071 #include "strtab.h" /* for strtab */ 00072 #include "symtab.h" /* for symtab */ 00073 #include "const.h" /* for constab */ 00074 #include "targ_const.h" /* for tcon */ 00075 #include "irbdata.h" /* for inito */ 00076 #include "config_targ.h" /* for Target_ABI */ 00077 #include "config_elf_targ.h" 00078 #include "wn_core.h" /* for WN */ 00079 #include "wn.h" /* for max_region_id */ 00080 #include "wn_map.h" /* for WN maps */ 00081 #include "dwarf_DST_mem.h" /* for dst */ 00082 #include "pu_info.h" 00083 #include "ir_elf.h" 00084 #include "ir_bwrite.h" 00085 #include "ir_bcom.h" 00086 #include "ir_bread.h" 00087 #include "tracing.h" /* TEMPORARY FOR ROBERT'S DEBUGGING */ 00088 00089 #ifdef BACK_END 00090 #include "glob.h" 00091 #include "pf_cg.h" 00092 #include "instr_reader.h" 00093 #include "fb_whirl.h" // for feedback stuff 00094 00095 BOOL Write_BE_Maps = FALSE; 00096 BOOL Write_AC_INTERNAL_Map = FALSE; 00097 BOOL Write_ALIAS_CLASS_Map = FALSE; 00098 00099 extern WN **prefetch_ldsts; 00100 extern INT num_prefetch_ldsts; 00101 extern INT max_num_prefetch_ldsts; 00102 00103 extern WN **alias_classes; 00104 extern INT num_alias_class_nodes; 00105 extern INT max_alias_class_nodes; 00106 00107 extern WN **ac_internals; 00108 extern INT num_ac_internal_nodes; 00109 extern INT max_ac_internal_nodes; 00110 00111 extern "C" { 00112 extern void *C_Dep_Graph(void); 00113 extern void Depgraph_Write (void *depgraph, Output_File *fl, WN_MAP off_map); 00114 } 00115 #endif /* BACK_END */ 00116 00117 00118 #define MMAP(addr, len, prot, flags, fd, off) \ 00119 mmap((void *)(addr), (size_t)(len), (int)(prot), (int)(flags), \ 00120 (int)(fd), (off_t)(off)) 00121 00122 #define MUNMAP(addr, len) \ 00123 munmap((char *)(addr), (size_t)(len)) 00124 00125 #define OPEN(path, flag, mode) \ 00126 open((const char *)(path), (int)(flag), (mode_t)(mode)) 00127 00128 00129 00130 extern "C" typedef void (*SIG_HANDLER)(int); 00131 00132 static SIG_HANDLER old_sigsegv; /* the previous signal handler */ 00133 static SIG_HANDLER old_sigbus; /* the previous signal handler */ 00134 00135 Output_File *Current_Output = 0; 00136 00137 #if !defined(__sgi) 00138 # define MAPPED_SIZE 0x400000 00139 #endif 00140 00141 static void 00142 cleanup (Output_File *fl) 00143 { 00144 fl->output_fd = -1; 00145 if (fl->num_of_section > 0) 00146 free (fl->section_list); 00147 fl->num_of_section = 0; 00148 fl->section_list = NULL; 00149 00150 // eraxxon: must have already called munmap() to support cygwin. 00151 // (See comments below.) 00152 //MUNMAP((char *)(fl->map_addr), (size_t)(fl->mapped_size)); 00153 fl->map_addr = NULL; 00154 fl->file_size = 0; 00155 } /* cleanup */ 00156 00157 00158 /* Low-level I/O routines */ 00159 00160 00161 /* we steal the signal handler for SIGSEGV/SIGBUS when we create the mmap 00162 * because SIGSEGV/SIGBUS caused by operations on the mapped regions needs 00163 * to be handled differently. We keep the old signal handler in 00164 * "old_sigsegv/old_sigbus", to which we pass the non-mmap related SIGSEGV. 00165 */ 00166 extern "C" void 00167 ir_bwrite_signal_handler (int sig, int err_num) 00168 { 00169 SIG_HANDLER old_handler = 0; 00170 00171 if (Doing_mmapped_io && err_num > 0) { 00172 Fatal_Error ("I/O error in %s: %s", Current_Output ? 00173 Current_Output->file_name : "mmapped object", 00174 strerror(err_num)); 00175 } 00176 00177 switch (sig) { 00178 case SIGBUS: 00179 old_handler = old_sigbus; 00180 break; 00181 case SIGSEGV: 00182 old_handler = old_sigsegv; 00183 break; 00184 } 00185 00186 if (old_handler == SIG_DFL) { 00187 /* resignal - will get default handler */ 00188 kill(getpid(), sig); 00189 } else if (old_handler != SIG_IGN) { 00190 /* call old handler */ 00191 (*old_handler)(sig); 00192 } 00193 return; 00194 00195 } /* ir_bwrite_signal_handler */ 00196 00197 00198 00199 00200 /* Elf-related routines */ 00201 #define DEFAULT_NUM_OF_SECTIONS 8 00202 00203 static Section * 00204 get_section (Elf64_Word sh_info, char *name, Output_File *fl) 00205 { 00206 register INT i; 00207 00208 for (i = 0; i < fl->num_of_section; i++) { 00209 if ((fl->section_list[i].shdr.sh_info == sh_info) && 00210 (strcmp (fl->section_list[i].name, name) == 0)) { 00211 fl->cur_section = fl->section_list + i; 00212 return fl->cur_section; 00213 } 00214 } 00215 00216 if (fl->num_of_section == 0) { 00217 fl->max_num_of_section = DEFAULT_NUM_OF_SECTIONS; 00218 fl->section_list = 00219 (Section *)malloc(fl->max_num_of_section * sizeof(Section)); 00220 FmtAssert (fl->section_list, ("No more memory")); 00221 } else if (fl->max_num_of_section == fl->num_of_section) { 00222 fl->max_num_of_section *= 2; 00223 fl->section_list = (Section *) realloc 00224 (fl->section_list, 00225 fl->max_num_of_section * sizeof(Section)); 00226 FmtAssert (fl->section_list, ("No more memory")); 00227 } 00228 00229 fl->cur_section = fl->section_list + fl->num_of_section; 00230 fl->num_of_section += 1; 00231 00232 memset (fl->cur_section, 0, sizeof(Section)); 00233 fl->cur_section->name = name; 00234 fl->cur_section->shdr.sh_info = sh_info; 00235 fl->cur_section->shdr.sh_type = SHT_MIPS_WHIRL; 00236 00237 return fl->cur_section; 00238 } /* get_section */ 00239 00240 00241 template <class Shdr> 00242 UINT64 00243 layout_sections (Shdr& strtab_sec, Output_File *fl) 00244 { 00245 UINT64 e_shoff; 00246 Elf64_Word strtab_size = 1; 00247 00248 for (INT i = 0; i < fl->num_of_section; i++) { 00249 Section& sec = fl->section_list[i]; 00250 sec.shdr.sh_name = strtab_size; 00251 strtab_size += strlen(sec.name) + 1; 00252 } 00253 00254 memset (&strtab_sec, 0, sizeof(Shdr)); 00255 strtab_sec.sh_name = strtab_size; 00256 strtab_size += strlen (ELF_SHSTRTAB) + 1; 00257 strtab_sec.sh_type = SHT_STRTAB; 00258 strtab_sec.sh_size = strtab_size; 00259 strtab_sec.sh_offset = fl->file_size; 00260 fl->file_size += strtab_size; 00261 strtab_sec.sh_addralign = 1; 00262 strtab_sec.sh_entsize = 1; 00263 00264 fl->file_size = ir_b_align (fl->file_size, ALIGNOF(Shdr), 0); 00265 e_shoff = fl->file_size; 00266 00267 /* There are 2 extra sections: the null and the section string table */ 00268 fl->file_size += sizeof(Shdr) * (fl->num_of_section + 2); 00269 00270 /* make sure the entire file is mapped */ 00271 if (fl->file_size >= fl->mapped_size) 00272 ir_b_grow_map (0, fl); 00273 00274 return e_shoff; 00275 } /* layout_sections */ 00276 00277 00278 // Solaris CC workaround the template function "write_output()" causes 00279 // "Assertion error" with CC compiler when -g is present, to solve 00280 // this problem, I removed the template definition and replaced it 00281 // with explicit overloaded definition. The following two definitions 00282 // are for "ELF32" and "ELF64", respectively. 00283 // 00284 #if !defined(__GNUC__) && defined(_SOLARIS_SOLARIS) 00285 00286 #ifdef ELF 00287 #undef ELF 00288 #endif 00289 #define ELF ELF64 00290 static void 00291 write_output (UINT64 e_shoff, const typename ELF::Elf_Shdr& strtab_sec, 00292 Output_File *fl, const ELF& tag) 00293 { 00294 INT i; 00295 char *base_addr = fl->map_addr; 00296 00297 /* write Elf header */ 00298 typename ELF::Elf_Ehdr* ehdr = (typename ELF::Elf_Ehdr *) fl->map_addr; 00299 strcpy ((char *) ehdr->e_ident, ELFMAG); 00300 ehdr->e_ident[EI_CLASS] = tag.Elf_class (); 00301 #if (defined(__sgi) || defined(__sun) || defined(__MACH__)) 00302 ehdr->e_ident[EI_DATA] = ELFDATA2MSB; /* assume MSB for now */ 00303 #else 00304 ehdr->e_ident[EI_DATA] = ELFDATA2LSB; /* assume LSB for now */ 00305 #endif 00306 ehdr->e_ident[EI_VERSION] = EV_CURRENT; 00307 ehdr->e_type = ET_IR; 00308 ehdr->e_machine = Get_Elf_Target_Machine(); 00309 ehdr->e_version = EV_CURRENT; 00310 ehdr->e_shoff = e_shoff; 00311 ehdr->e_flags = Config_ELF_From_Target (! Use_32_Bit_Pointers, FALSE, 00312 (INT) Target_ISA); 00313 ehdr->e_ehsize = sizeof(ELF::Elf_Ehdr); 00314 ehdr->e_shentsize = sizeof(ELF::Elf_Shdr); 00315 ehdr->e_shnum = fl->num_of_section + 2; 00316 ehdr->e_shstrndx = fl->num_of_section + 1; 00317 00318 /* the section string table */ 00319 char* str = base_addr + strtab_sec.sh_offset; 00320 str[0] = '\0'; 00321 str++; 00322 for (i = 0; i < fl->num_of_section; i++) { 00323 strcpy (str, fl->section_list[i].name); 00324 str += strlen (str) + 1; 00325 } 00326 strcpy (str, ELF_SHSTRTAB); 00327 00328 /* simple check to see if layout has been done right */ 00329 if ((INTPTR)str + strlen(ELF_SHSTRTAB) + 1 > 00330 e_shoff + (INTPTR) base_addr) 00331 ErrMsg (EC_IR_Scn_Write, "Section Header String Table", fl->file_name); 00332 00333 /* Finally, the section header table */ 00334 typename ELF::Elf_Shdr* shdr = 00335 (typename ELF::Elf_Shdr *) (base_addr + e_shoff); 00336 memset (shdr, 0, sizeof(ELF::Elf_Shdr)); /* First null entry */ 00337 shdr++; 00338 if (tag.Elf_class() == ELFCLASS64) { 00339 for (i = 0; i < fl->num_of_section; i++, shdr++) 00340 memcpy (shdr, &(fl->section_list[i].shdr), sizeof(ELF::Elf_Shdr)); 00341 } else { 00342 // convert Elf64_Shdr to Elf32_Shdr 00343 for (i = 0; i < fl->num_of_section; i++, shdr++) { 00344 shdr->sh_name = fl->section_list[i].shdr.sh_name; 00345 shdr->sh_type = fl->section_list[i].shdr.sh_type; 00346 shdr->sh_flags = fl->section_list[i].shdr.sh_flags; 00347 shdr->sh_addr = fl->section_list[i].shdr.sh_addr; 00348 shdr->sh_offset = fl->section_list[i].shdr.sh_offset; 00349 shdr->sh_size = fl->section_list[i].shdr.sh_size; 00350 shdr->sh_link = fl->section_list[i].shdr.sh_link; 00351 shdr->sh_info = fl->section_list[i].shdr.sh_info; 00352 shdr->sh_addralign = fl->section_list[i].shdr.sh_addralign; 00353 shdr->sh_entsize = fl->section_list[i].shdr.sh_entsize; 00354 } 00355 } 00356 memcpy (shdr, &strtab_sec, sizeof(ELF::Elf_Shdr)); 00357 } /* write_output */ 00358 00359 // Solaris CC workaround 00360 // as mentioned earlier, following is the definition on "ELF32" 00361 00362 #ifdef ELF 00363 #undef ELF 00364 #endif 00365 #define ELF ELF32 00366 static void 00367 write_output (UINT64 e_shoff, const typename ELF::Elf_Shdr& strtab_sec, 00368 Output_File *fl, const ELF& tag) 00369 { 00370 INT i; 00371 char *base_addr = fl->map_addr; 00372 00373 /* write Elf header */ 00374 typename ELF::Elf_Ehdr* ehdr = (typename ELF::Elf_Ehdr *) fl->map_addr; 00375 strcpy ((char *) ehdr->e_ident, ELFMAG); 00376 ehdr->e_ident[EI_CLASS] = tag.Elf_class (); 00377 #if (defined(__sgi) || defined(__sun) || defined(__MACH__)) 00378 ehdr->e_ident[EI_DATA] = ELFDATA2MSB; /* assume MSB for now */ 00379 #else 00380 ehdr->e_ident[EI_DATA] = ELFDATA2LSB; /* assume LSB for now */ 00381 #endif 00382 ehdr->e_ident[EI_VERSION] = EV_CURRENT; 00383 ehdr->e_type = ET_IR; 00384 ehdr->e_machine = Get_Elf_Target_Machine(); 00385 ehdr->e_version = EV_CURRENT; 00386 ehdr->e_shoff = e_shoff; 00387 ehdr->e_flags = Config_ELF_From_Target (! Use_32_Bit_Pointers, FALSE, 00388 (INT) Target_ISA); 00389 ehdr->e_ehsize = sizeof(ELF::Elf_Ehdr); 00390 ehdr->e_shentsize = sizeof(ELF::Elf_Shdr); 00391 ehdr->e_shnum = fl->num_of_section + 2; 00392 ehdr->e_shstrndx = fl->num_of_section + 1; 00393 00394 /* the section string table */ 00395 char* str = base_addr + strtab_sec.sh_offset; 00396 str[0] = '\0'; 00397 str++; 00398 for (i = 0; i < fl->num_of_section; i++) { 00399 strcpy (str, fl->section_list[i].name); 00400 str += strlen (str) + 1; 00401 } 00402 strcpy (str, ELF_SHSTRTAB); 00403 00404 /* simple check to see if layout has been done right */ 00405 if ((INTPTR)str + strlen(ELF_SHSTRTAB) + 1 > 00406 e_shoff + (INTPTR) base_addr) 00407 ErrMsg (EC_IR_Scn_Write, "Section Header String Table", fl->file_name); 00408 00409 /* Finally, the section header table */ 00410 typename ELF::Elf_Shdr* shdr = 00411 (typename ELF::Elf_Shdr *) (base_addr + e_shoff); 00412 memset (shdr, 0, sizeof(ELF::Elf_Shdr)); /* First null entry */ 00413 shdr++; 00414 if (tag.Elf_class() == ELFCLASS64) { 00415 for (i = 0; i < fl->num_of_section; i++, shdr++) 00416 memcpy (shdr, &(fl->section_list[i].shdr), sizeof(ELF::Elf_Shdr)); 00417 } else { 00418 // convert Elf64_Shdr to Elf32_Shdr 00419 for (i = 0; i < fl->num_of_section; i++, shdr++) { 00420 shdr->sh_name = fl->section_list[i].shdr.sh_name; 00421 shdr->sh_type = fl->section_list[i].shdr.sh_type; 00422 shdr->sh_flags = fl->section_list[i].shdr.sh_flags; 00423 shdr->sh_addr = fl->section_list[i].shdr.sh_addr; 00424 shdr->sh_offset = fl->section_list[i].shdr.sh_offset; 00425 shdr->sh_size = fl->section_list[i].shdr.sh_size; 00426 shdr->sh_link = fl->section_list[i].shdr.sh_link; 00427 shdr->sh_info = fl->section_list[i].shdr.sh_info; 00428 shdr->sh_addralign = fl->section_list[i].shdr.sh_addralign; 00429 shdr->sh_entsize = fl->section_list[i].shdr.sh_entsize; 00430 } 00431 } 00432 memcpy (shdr, &strtab_sec, sizeof(ELF::Elf_Shdr)); 00433 } /* write_output */ 00434 00435 #undef ELF 00436 // don't forget to undefine ELF, just for safety. 00437 00438 #else // __GNUC__ _SOLARIS_SOLARIS 00439 // remove the template definition, see the comments above for details. 00440 00441 template <class ELF> 00442 static void 00443 write_output (UINT64 e_shoff, const typename ELF::Elf_Shdr& strtab_sec, 00444 Output_File *fl, const ELF& tag) 00445 { 00446 INT i; 00447 char *base_addr = fl->map_addr; 00448 00449 /* write Elf header */ 00450 typename ELF::Elf_Ehdr* ehdr = (typename ELF::Elf_Ehdr *) fl->map_addr; 00451 strcpy ((char *) ehdr->e_ident, ELFMAG); 00452 ehdr->e_ident[EI_CLASS] = tag.Elf_class (); 00453 #if (defined(__sgi) || defined(__sun) || defined(__MACH__)) 00454 ehdr->e_ident[EI_DATA] = ELFDATA2MSB; /* assume MSB for now */ 00455 #else 00456 ehdr->e_ident[EI_DATA] = ELFDATA2LSB; /* assume LSB for now */ 00457 #endif 00458 ehdr->e_ident[EI_VERSION] = EV_CURRENT; 00459 ehdr->e_type = ET_IR; 00460 ehdr->e_machine = Get_Elf_Target_Machine(); 00461 ehdr->e_version = EV_CURRENT; 00462 ehdr->e_shoff = e_shoff; 00463 ehdr->e_flags = Config_ELF_From_Target (! Use_32_Bit_Pointers, FALSE, 00464 (INT) Target_ISA); 00465 ehdr->e_ehsize = sizeof(typename ELF::Elf_Ehdr); 00466 ehdr->e_shentsize = sizeof(typename ELF::Elf_Shdr); 00467 ehdr->e_shnum = fl->num_of_section + 2; 00468 ehdr->e_shstrndx = fl->num_of_section + 1; 00469 00470 /* the section string table */ 00471 char* str = base_addr + strtab_sec.sh_offset; 00472 str[0] = '\0'; 00473 str++; 00474 for (i = 0; i < fl->num_of_section; i++) { 00475 strcpy (str, fl->section_list[i].name); 00476 str += strlen (str) + 1; 00477 } 00478 strcpy (str, ELF_SHSTRTAB); 00479 00480 /* simple check to see if layout has been done right */ 00481 if ((INTPTR)str + strlen(ELF_SHSTRTAB) + 1 > 00482 e_shoff + (INTPTR) base_addr) 00483 ErrMsg (EC_IR_Scn_Write, "Section Header String Table", fl->file_name); 00484 00485 /* Finally, the section header table */ 00486 typename ELF::Elf_Shdr* shdr = 00487 (typename ELF::Elf_Shdr *) (base_addr + e_shoff); 00488 memset (shdr, 0, sizeof(typename ELF::Elf_Shdr)); /* First null entry */ 00489 shdr++; 00490 if (tag.Elf_class() == ELFCLASS64) { 00491 for (i = 0; i < fl->num_of_section; i++, shdr++) 00492 memcpy (shdr, &(fl->section_list[i].shdr), 00493 sizeof(typename ELF::Elf_Shdr)); 00494 } else { 00495 // convert Elf64_Shdr to Elf32_Shdr 00496 for (i = 0; i < fl->num_of_section; i++, shdr++) { 00497 shdr->sh_name = fl->section_list[i].shdr.sh_name; 00498 shdr->sh_type = fl->section_list[i].shdr.sh_type; 00499 shdr->sh_flags = fl->section_list[i].shdr.sh_flags; 00500 shdr->sh_addr = fl->section_list[i].shdr.sh_addr; 00501 shdr->sh_offset = fl->section_list[i].shdr.sh_offset; 00502 shdr->sh_size = fl->section_list[i].shdr.sh_size; 00503 shdr->sh_link = fl->section_list[i].shdr.sh_link; 00504 shdr->sh_info = fl->section_list[i].shdr.sh_info; 00505 shdr->sh_addralign = fl->section_list[i].shdr.sh_addralign; 00506 shdr->sh_entsize = fl->section_list[i].shdr.sh_entsize; 00507 } 00508 } 00509 memcpy (shdr, &strtab_sec, sizeof(typename ELF::Elf_Shdr)); 00510 } /* write_output */ 00511 00512 #endif // __GNUC__ _SOLARIX_SOLARIS 00513 00514 00515 /* 00516 * open and create a temporary file, then unlink it right away so that the 00517 * file will be gone as soon as it is closed. 00518 */ 00519 00520 #define DEFAULT_TMPDIR "/usr/tmp" 00521 #define DEFAULT_TEMPLATE "/elf_wnXXXXXX" 00522 00523 static int 00524 create_temp_file (Output_File *fl) 00525 { 00526 register char *tmpdir; 00527 register char *path; 00528 register int fd; 00529 00530 if ((tmpdir = getenv("TMPDIR")) == 0) 00531 tmpdir = DEFAULT_TMPDIR; 00532 path = (char *) malloc (strlen(tmpdir) + strlen(DEFAULT_TEMPLATE) + 1); 00533 if (path == 0) 00534 return -1; 00535 strcpy (path, tmpdir); 00536 strcat (path, DEFAULT_TEMPLATE); 00537 fd = ux_mkstemp (path); 00538 if (fd != -1) 00539 unlink (path); 00540 00541 fl->file_name = path; 00542 return fd; 00543 } /* create_temp_file */ 00544 00545 00546 /* The followings are exported functions. */ 00547 00548 /* 00549 * Open an output file for writing and return an Output_File structure 00550 * to record the current state of that file. If no file name is given, 00551 * a temporary file will be created. More than one file may be 00552 * open at once. Returns NULL if the file cannot be opened. 00553 */ 00554 00555 Output_File * 00556 WN_open_output (const char *file_name) 00557 { 00558 Output_File *fl; 00559 Section *cur_section; 00560 00561 // Solaris CC error 00562 // compiler complains that "Could not find a match for std::signal(int, 00563 // void(*)(int))." Not sure how to solve this problem yet! 00564 // okay, just add std:: before signal and it will compile 00565 00566 if (old_sigsegv == 0) 00567 #ifdef _SOLARIS_SOLARIS 00568 old_sigsegv = std::signal (SIGSEGV, reinterpret_cast<SIG_HANDLER> 00569 (ir_bwrite_signal_handler)); 00570 #else 00571 old_sigsegv = signal (SIGSEGV, reinterpret_cast<SIG_HANDLER> 00572 (ir_bwrite_signal_handler)); 00573 #endif 00574 00575 if (old_sigbus == 0) 00576 #ifdef _SOLARIS_SOLARIS 00577 old_sigbus = std::signal (SIGBUS, reinterpret_cast<SIG_HANDLER> 00578 (ir_bwrite_signal_handler)); 00579 #else 00580 old_sigbus = signal (SIGBUS, reinterpret_cast<SIG_HANDLER> 00581 (ir_bwrite_signal_handler)); 00582 #endif 00583 00584 fl = (Output_File *)malloc(sizeof(Output_File)); 00585 if (!fl) return NULL; 00586 00587 if (file_name == 0) { 00588 fl->output_fd = create_temp_file (fl); 00589 } else { 00590 fl->file_name = file_name; 00591 // set mode to rw for all; users umask will AND with that. 00592 fl->output_fd = OPEN (file_name, O_RDWR|O_CREAT|O_TRUNC, 0666); 00593 } 00594 if (fl->output_fd < 0) 00595 return NULL; 00596 00597 // mmap() normally cannot automatically increase file size, so we 00598 // allocate some space using ftruncate(). SGI's mmap() can avoid 00599 // this. cf. use of ftruncate() in ir_bcom.cxx. 00600 #if !defined(__sgi) 00601 ftruncate(fl->output_fd, MAPPED_SIZE); 00602 #endif 00603 00604 fl->section_list = NULL; 00605 fl->cur_section = NULL; 00606 fl->num_of_section = 0; 00607 00608 /* initialize the output map */ 00609 if (ir_b_create_map (fl) == (char *) (-1)) 00610 return NULL; 00611 00612 /* leave space for the Elf header */ 00613 #ifdef __ALWAYS_USE_64BIT_ELF__ 00614 fl->file_size = sizeof(Elf64_Ehdr); 00615 #else 00616 fl->file_size = Use_32_Bit_Pointers ? 00617 sizeof(Elf32_Ehdr) : sizeof(Elf64_Ehdr); 00618 #endif 00619 00620 /* go to the PU-specific section */ 00621 cur_section = get_section (WT_PU_SECTION, MIPS_WHIRL_PU_SECTION, fl); 00622 00623 fl->file_size = ir_b_align (fl->file_size, sizeof(mUINT64), 0); 00624 cur_section->shdr.sh_offset = fl->file_size; 00625 00626 /* leave space for a pointer to the PU-section header */ 00627 fl->file_size += sizeof(Elf64_Word); 00628 00629 return fl; 00630 } /* WN_open_output */ 00631 00632 00633 /* 00634 * Write out the PU-section header. This routine is called after all the 00635 * PUs have been written out. 00636 */ 00637 00638 void 00639 WN_write_PU_Infos (PU_Info *pu_list, Output_File *fl) 00640 { 00641 INT32 hdr_sz; 00642 Section *cur_section = fl->cur_section; 00643 00644 /* make sure we're in the right section */ 00645 if (strcmp(cur_section->name, MIPS_WHIRL_PU_SECTION) != 0) 00646 ErrMsg (EC_IR_Scn_Write, "PU headers", fl->file_name); 00647 00648 fl->file_size = ir_b_align (fl->file_size, sizeof(mINT32), 0); 00649 00650 /* record the header offset at the beginning of the section */ 00651 *(Elf64_Word *)(fl->map_addr + cur_section->shdr.sh_offset) = 00652 (Elf64_Word)(fl->file_size - cur_section->shdr.sh_offset); 00653 00654 hdr_sz = Sizeof_PU_Infos (pu_list); 00655 00656 /* allocate space in the output file */ 00657 if (fl->file_size + hdr_sz >= fl->mapped_size) 00658 ir_b_grow_map (hdr_sz, fl); 00659 00660 if (Write_PU_Infos (pu_list, fl->map_addr + fl->file_size) == -1) 00661 ErrMsg (EC_IR_Scn_Write, "PU headers", fl->file_name); 00662 fl->file_size += hdr_sz; 00663 00664 cur_section->shdr.sh_size = fl->file_size - cur_section->shdr.sh_offset; 00665 /* some data structures placed in the WHIRL_PU_SECTION needs to be 00666 64bit aligned, even though the pu_info structure itself is not */ 00667 cur_section->shdr.sh_addralign = sizeof(mINT64); 00668 } /* WN_write_PU_Infos */ 00669 00670 00671 /* 00672 * Write out a tree. This routine traverse the specified tree and writes 00673 * out every node in that tree. The tree nodes are assumed valid and no 00674 * validation is performed. The size and offset of the output subsection 00675 * are stored in the PU_Info structure. The subsection offsets of the WNs 00676 * are stored in a map specified by the "off_map" parameter, so that they 00677 * can be used when writing out information associated with the tree 00678 * (e.g. dependence graphs). Memory occupied by the tree can be freed 00679 * after it is written out. 00680 */ 00681 00682 void 00683 WN_write_tree (PU_Info *pu, WN_MAP off_map, Output_File *fl) 00684 { 00685 static char *scn_name = "tree"; 00686 UINT padding; 00687 Elf64_Word this_tree; 00688 WN *tree; 00689 off_t tree_base; 00690 Section *cur_section = fl->cur_section; 00691 00692 /* make sure we're in the right section */ 00693 if (strcmp(cur_section->name, MIPS_WHIRL_PU_SECTION) != 0 || 00694 PU_Info_state(pu, WT_TREE) != Subsect_InMem) 00695 ErrMsg (EC_IR_Scn_Write, scn_name, fl->file_name); 00696 00697 tree = PU_Info_tree_ptr(pu); 00698 00699 #ifdef BACK_END 00700 if (Write_BE_Maps) { 00701 /* initialize globals used to record nodes with prefetch pointers */ 00702 prefetch_ldsts = NULL; 00703 num_prefetch_ldsts = 0; 00704 max_num_prefetch_ldsts = 0; 00705 } 00706 00707 if (Write_ALIAS_CLASS_Map) { 00708 /* globals used to record nodes with alias classification 00709 * information 00710 */ 00711 alias_classes = NULL; 00712 num_alias_class_nodes = 0; 00713 max_alias_class_nodes = 0; 00714 } 00715 00716 if (Write_AC_INTERNAL_Map) { 00717 /* globals used to record nodes with alias classification's 00718 * internal information for indirect memops 00719 */ 00720 ac_internals = NULL; 00721 num_ac_internal_nodes = 0; 00722 max_ac_internal_nodes = 0; 00723 } 00724 #endif 00725 00726 padding = ((char *)tree) - (char *)WN_StartAddress(tree); 00727 if (padding == 0) { 00728 /* root of tree must have prev/next pointers */ 00729 ErrMsg (EC_IR_Scn_Write, scn_name, fl->file_name); 00730 } 00731 /* add room for offset to the first node */ 00732 padding += sizeof(Elf64_Word); 00733 fl->file_size = ir_b_align (fl->file_size, ALIGNOF(WN), padding); 00734 tree_base = fl->file_size; 00735 00736 this_tree = ir_b_write_tree (tree, tree_base, fl, off_map); 00737 00738 /* save the offset to the first node */ 00739 *(Elf64_Word *)(fl->map_addr + tree_base) = this_tree; 00740 00741 #ifdef BACK_END 00742 /* stash the array of nodes with prefetches in the PU_Info */ 00743 if (Write_BE_Maps && num_prefetch_ldsts > 0) { 00744 /* mark the end (must have already allocated space for the marker) */ 00745 prefetch_ldsts[num_prefetch_ldsts] = NULL; 00746 PU_Info_subsect_ptr(pu, WT_PREFETCH) = (void *)prefetch_ldsts; 00747 Set_PU_Info_state(pu, WT_PREFETCH, Subsect_InMem); 00748 } 00749 00750 if (Write_ALIAS_CLASS_Map && num_alias_class_nodes > 0) { 00751 alias_classes[num_alias_class_nodes] = NULL; 00752 Set_PU_Info_alias_class_ptr(pu, alias_classes); 00753 Set_PU_Info_state(pu, WT_ALIAS_CLASS, Subsect_InMem); 00754 } 00755 00756 if (Write_AC_INTERNAL_Map && num_ac_internal_nodes > 0) { 00757 ac_internals[num_ac_internal_nodes] = NULL; 00758 Set_PU_Info_ac_internal_ptr(pu, ac_internals); 00759 Set_PU_Info_state(pu, WT_AC_INTERNAL, Subsect_InMem); 00760 } 00761 #endif 00762 00763 Set_PU_Info_state(pu, WT_TREE, Subsect_Written); 00764 PU_Info_subsect_size(pu, WT_TREE) = fl->file_size - tree_base; 00765 PU_Info_subsect_offset(pu, WT_TREE) = 00766 tree_base - cur_section->shdr.sh_offset; 00767 00768 Set_Max_Region_Id(0); /* reset max region id for pu */ 00769 00770 } /* WN_write_tree */ 00771 00772 00773 /* 00774 * Write out the command and arguments needed to compile this IR. The 00775 * arguments are in the standard argc, argv formats. 00776 */ 00777 00778 void 00779 WN_write_flags (INT argc, char **argv, Output_File *fl) 00780 { 00781 INT i, argv_size; 00782 off_t offset; 00783 Elf64_Word argc_buf = argc; 00784 Section *cur_section; 00785 00786 FmtAssert (argc > 0 && argv != 0, ("invalid argument to WN_write_flags()")); 00787 00788 cur_section = get_section (WT_COMP_FLAGS, MIPS_WHIRL_COMP_FLAGS, fl); 00789 00790 fl->file_size = ir_b_align (fl->file_size, sizeof(Elf64_Word), 0); 00791 cur_section->shdr.sh_offset = fl->file_size; 00792 00793 /* First, write out argc */ 00794 ir_b_save_buf (&argc_buf, sizeof(Elf64_Word), sizeof(Elf64_Word), 0, fl); 00795 00796 /* Second, write out argv. Because we need to convert the argv array 00797 from pointers to Elf64_Words, we just increment the file_size by 00798 the appropriate amount instead of using save_buf. We then go back 00799 and fill in the values when writing out the actual argv strings. */ 00800 00801 fl->file_size = ir_b_align (fl->file_size, sizeof(Elf64_Word), 0); 00802 argv_size = sizeof(Elf64_Word) * argc; 00803 if (fl->file_size + argv_size >= fl->mapped_size) 00804 ir_b_grow_map (argv_size, fl); 00805 00806 offset = fl->file_size; 00807 fl->file_size += argv_size; 00808 00809 for (i = 0; i < argc; i++) { 00810 INT len = strlen(argv[i]) + 1; 00811 Elf64_Word string_offset, *argv_ptr; 00812 00813 string_offset = ir_b_save_buf (argv[i], len, 0, 0, fl); 00814 00815 /* the following statement is NOT loop-invariant since the file 00816 may be remapped at a different address when writing the strings */ 00817 argv_ptr = (Elf64_Word *) (fl->map_addr + offset); 00818 00819 argv_ptr[i] = string_offset - cur_section->shdr.sh_offset; 00820 } 00821 00822 cur_section->shdr.sh_size = fl->file_size - cur_section->shdr.sh_offset; 00823 cur_section->shdr.sh_addralign = sizeof(Elf64_Word); 00824 00825 } /* WN_write_flags */ 00826 00827 00828 /* 00829 * Write out the global symbol table. Unlike the local symtabs, the 00830 * global table gets its own Elf section and can only be written out 00831 * once. 00832 */ 00833 00834 00835 void 00836 WN_write_globals (Output_File *fl) 00837 { 00838 Section *cur_section = get_section (WT_GLOBALS, MIPS_WHIRL_GLOBALS, fl); 00839 00840 fl->file_size = ir_b_align (fl->file_size, sizeof(mINT64), 0); 00841 cur_section->shdr.sh_offset = fl->file_size; 00842 00843 (void) ir_b_write_global_symtab (fl->file_size, fl); 00844 00845 cur_section->shdr.sh_size = fl->file_size - cur_section->shdr.sh_offset; 00846 cur_section->shdr.sh_addralign = sizeof(mINT64); 00847 00848 } // WN_write_globals 00849 00850 00851 void 00852 WN_write_symtab (PU_Info *pu, Output_File *fl) 00853 { 00854 Section *cur_section = fl->cur_section; 00855 00856 /* make sure we're in the right section */ 00857 if (strcmp(cur_section->name, MIPS_WHIRL_PU_SECTION) != 0 || 00858 PU_Info_state(pu, WT_SYMTAB) != Subsect_InMem) 00859 ErrMsg (EC_IR_Scn_Write, "local symtab", fl->file_name); 00860 00861 const SCOPE& scope = 00862 Scope_tab[PU_lexical_level (&St_Table[PU_Info_proc_sym(pu)])]; 00863 00864 fl->file_size = ir_b_align (fl->file_size, sizeof(mINT64), 0); 00865 off_t symtab_base = fl->file_size; 00866 00867 (void)ir_b_write_local_symtab (scope, symtab_base, fl); 00868 00869 Set_PU_Info_state(pu, WT_SYMTAB, Subsect_Written); 00870 PU_Info_subsect_size(pu, WT_SYMTAB) = fl->file_size - symtab_base; 00871 PU_Info_subsect_offset(pu, WT_SYMTAB) = 00872 symtab_base - cur_section->shdr.sh_offset; 00873 } // WN_write_symtab 00874 00875 extern "C" void 00876 WN_write_strtab (const void* strtab, UINT64 size, Output_File *fl) 00877 { 00878 Section *cur_section = get_section (WT_STRTAB, MIPS_WHIRL_STRTAB, fl); 00879 00880 fl->file_size = ir_b_align (fl->file_size, sizeof(char), 0); 00881 cur_section->shdr.sh_offset = fl->file_size; 00882 00883 (void) ir_b_save_buf (strtab, size, sizeof(char), 0, fl); 00884 00885 cur_section->shdr.sh_size = fl->file_size - cur_section->shdr.sh_offset; 00886 cur_section->shdr.sh_addralign = sizeof(char); 00887 00888 } // WN_write_strtab 00889 00890 00891 /* 00892 * Write out the debug symbol table (dst). The DST gets its own Elf 00893 * section and should only be written once per file. 00894 */ 00895 00896 void 00897 WN_write_dst (DST_TYPE dst, Output_File *fl) 00898 { 00899 off_t dst_base; 00900 Section *cur_section; 00901 00902 cur_section = get_section (WT_DST, MIPS_WHIRL_DST, fl); 00903 00904 fl->file_size = ir_b_align (fl->file_size, sizeof(mINT32), 0); 00905 cur_section->shdr.sh_offset = fl->file_size; 00906 dst_base = fl->file_size; 00907 00908 (void) ir_b_write_dst (dst, dst_base, fl); 00909 00910 cur_section->shdr.sh_size = fl->file_size - cur_section->shdr.sh_offset; 00911 cur_section->shdr.sh_addralign = sizeof(mINT32); 00912 00913 } /* WN_write_dst */ 00914 00915 00916 #ifdef BACK_END 00917 00918 namespace 00919 { 00920 // local templates used only by WN_write_feedback 00921 00922 template <class T> 00923 void 00924 write_profile (off_t base, const T& data, Output_File* fl, mUINT32& num, 00925 mUINT32& offset) { 00926 offset = 00927 ir_b_save_buf (&(data.front()), 00928 data.size () * sizeof(typename T::value_type), 00929 ALIGNOF(typename T::value_type), 0, fl) - base; 00930 num = data.size (); 00931 } 00932 00933 template <class T> 00934 void 00935 write_target_profile (off_t base, T& data, Output_File* fl, 00936 mUINT32& num, mUINT32& offset, 00937 mUINT32& target_offset) { 00938 num = data.size (); 00939 fl->file_size = ir_b_align (fl->file_size, sizeof(mINT64), 0); 00940 offset = fl->file_size - base; 00941 00942 typename T::iterator first (data.begin ()); 00943 while (first != data.end ()) { 00944 const vector<FB_FREQ>& freq = first->freq_targets; 00945 ir_b_save_buf (&(freq.front ()), freq.size () * sizeof(FB_FREQ), 00946 ALIGNOF(FB_FREQ), 0, fl); 00947 ++first; 00948 } 00949 00950 target_offset = fl->file_size - base; 00951 first = data.begin (); 00952 while (first != data.end ()) { 00953 INT32 num = first->freq_targets.size (); 00954 ir_b_save_buf (&num, sizeof(INT32), sizeof(INT32), 0, fl); 00955 ++first; 00956 } 00957 } 00958 } 00959 00960 00961 00962 /* 00963 * Write out the IPA summary information. 00964 */ 00965 00966 void 00967 IPA_write_summary (void (*IPA_irb_write_summary) (Output_File*), 00968 Output_File *fl) 00969 { 00970 Section *cur_section; 00971 00972 cur_section = get_section(WT_IPA_SUMMARY, MIPS_WHIRL_SUMMARY, fl); 00973 00974 fl->file_size = ir_b_align(fl->file_size, sizeof(mINT64), 0); 00975 cur_section->shdr.sh_offset = fl->file_size; 00976 00977 (*IPA_irb_write_summary) (fl); 00978 00979 cur_section->shdr.sh_size = fl->file_size - cur_section->shdr.sh_offset; 00980 cur_section->shdr.sh_addralign = sizeof(mINT64); 00981 00982 } 00983 00984 00985 00986 /* 00987 * Write out the prefetch pointer mapping. The prefetch mappings are written 00988 * to PU subsections. The size and offset of the output subsection are 00989 * stored in the PU_Info structure. The off_map mapping must contain the 00990 * subsection offsets for the WN nodes referenced from the prefetch nodes. 00991 * To avoid making a second pass through the WHIRL tree, we rely on the 00992 * WN_write_tree routine to provide an array of the WNs with prefetch 00993 * pointers in the PU_Info. 00994 */ 00995 00996 void 00997 WN_write_prefetch (PU_Info *pu, WN_MAP off_map, Output_File *fl) 00998 { 00999 WN **pf_ldsts; 01000 off_t prefetch_base; 01001 Section *cur_section = fl->cur_section; 01002 INT i; 01003 WN *node; 01004 PF_POINTER *pf_ptr; 01005 INT32 cur_offset; 01006 Elf64_Word node_offset; 01007 01008 #define PF_PTR_ADDR(offset) ((PF_POINTER *)(fl->map_addr + (offset))) 01009 01010 if (PU_Info_state(pu, WT_PREFETCH) == Subsect_Missing) 01011 return; 01012 01013 /* make sure we're in the right section */ 01014 if (strcmp(cur_section->name, MIPS_WHIRL_PU_SECTION) != 0 || 01015 PU_Info_state(pu, WT_PREFETCH) != Subsect_InMem) 01016 ErrMsg (EC_IR_Scn_Write, "prefetch map", fl->file_name); 01017 01018 pf_ldsts = (WN **)PU_Info_subsect_ptr(pu, WT_PREFETCH); 01019 if (!pf_ldsts) { 01020 /* this should only happen if the prefetches were read in and then 01021 removed but we might as well check for it */ 01022 Set_PU_Info_state(pu, WT_PREFETCH, Subsect_Missing); 01023 return; 01024 } 01025 01026 fl->file_size = ir_b_align(fl->file_size, sizeof(mINT32), 0); 01027 prefetch_base = fl->file_size; 01028 01029 for (i = 0; pf_ldsts[i]; i++) { 01030 01031 node = pf_ldsts[i]; 01032 pf_ptr = (PF_POINTER *) WN_MAP_Get(WN_MAP_PREFETCH, node); 01033 01034 node_offset = (Elf64_Word)WN_MAP32_Get(off_map, node); 01035 cur_offset = ir_b_save_buf((void *)&node_offset, sizeof(Elf64_Word), 01036 sizeof(Elf64_Word), 0, fl); 01037 01038 cur_offset = ir_b_save_buf((void *)pf_ptr, sizeof(PF_POINTER), 01039 ALIGNOF(PF_POINTER), 0, fl); 01040 01041 /* change the WN pointers to offsets. Store a -1 if NULL pointer */ 01042 PF_PTR_ADDR(cur_offset)->wn_pref_1L = 01043 ((pf_ptr->wn_pref_1L) ? 01044 (WN *) WN_MAP32_Get(off_map, pf_ptr->wn_pref_1L) : 01045 (WN *) -1); 01046 PF_PTR_ADDR(cur_offset)->wn_pref_2L = 01047 ((pf_ptr->wn_pref_2L) ? 01048 (WN *) WN_MAP32_Get(off_map, pf_ptr->wn_pref_2L) : 01049 (WN *) -1); 01050 } 01051 01052 /* deallocate the array created by write_tree */ 01053 PU_Info_subsect_ptr(pu, WT_PREFETCH) = NULL; 01054 free(pf_ldsts); 01055 01056 /* write out a -1 to mark the end */ 01057 node_offset = (Elf64_Word)-1; 01058 ir_b_save_buf(&node_offset, sizeof(Elf64_Word), sizeof(Elf64_Word), 0, fl); 01059 01060 Set_PU_Info_state(pu, WT_PREFETCH, Subsect_Written); 01061 PU_Info_subsect_size(pu, WT_PREFETCH) = fl->file_size - prefetch_base; 01062 PU_Info_subsect_offset(pu, WT_PREFETCH) = 01063 prefetch_base - cur_section->shdr.sh_offset; 01064 01065 } /* WN_write_prefetch */ 01066 01067 01068 template<class MAP_ENTRY_TYPE> 01069 static inline MAP_ENTRY_TYPE 01070 WN_MAP_retrieve(WN_MAP, WN *, MAP_ENTRY_TYPE); 01071 01072 static inline INT32 01073 WN_MAP_retrieve(WN_MAP wn_map, WN *wn, INT32) 01074 { 01075 return WN_MAP32_Get(wn_map, wn); 01076 } 01077 01078 static inline INT64 01079 WN_MAP_retrieve(WN_MAP wn_map, WN *wn, INT64) 01080 { 01081 return WN_MAP64_Get(wn_map, wn); 01082 } 01083 01084 static inline void * 01085 WN_MAP_retrieve(WN_MAP wn_map, WN *wn, void *) 01086 { 01087 return WN_MAP_Get(wn_map, wn); 01088 } 01089 01090 // Write out an WHIRL mapping, such as an alias classification map, or 01091 // a frequency map. 01092 template<class MAP_ENTRY_TYPE> 01093 static inline void 01094 WN_write_generic_map(PU_Info *pu, 01095 WN_MAP off_map, 01096 Output_File *fl, 01097 INT32 subsection_type, 01098 WN_MAP value_map, 01099 const char *subsection_name, 01100 MAP_ENTRY_TYPE) 01101 { 01102 WN **nodes_represented; // WHIRL nodes that need map values recorded 01103 off_t mapping_base; // File offset of the mapping info 01104 Elf64_Word node_offset; // File offset of the current WN 01105 INT i; 01106 01107 if (PU_Info_state (pu, subsection_type) == Subsect_Missing) 01108 return; 01109 01110 if (strcmp (fl->cur_section->name, MIPS_WHIRL_PU_SECTION) != 0 || 01111 PU_Info_state(pu, subsection_type) != Subsect_InMem) { 01112 ErrMsg (EC_IR_Scn_Write, subsection_name, fl->file_name); 01113 } 01114 01115 nodes_represented = (WN **) PU_Info_subsect_ptr (pu, subsection_type); 01116 if (!nodes_represented) { 01117 Set_PU_Info_state(pu, subsection_type, Subsect_Missing); 01118 return; 01119 } 01120 01121 fl->file_size = ir_b_align (fl->file_size, sizeof(mINT64), 0); 01122 mapping_base = fl->file_size; 01123 01124 for (i = 0; nodes_represented[i]; i++) { 01125 WN *node = nodes_represented[i]; 01126 MAP_ENTRY_TYPE map_value = WN_MAP_retrieve(value_map, 01127 node, 01128 (MAP_ENTRY_TYPE) 0); 01129 if (map_value != (MAP_ENTRY_TYPE) 0) { 01130 node_offset = WN_MAP32_Get(off_map, node); 01131 (void) ir_b_save_buf ((void*) &node_offset, sizeof(Elf64_Word), 01132 sizeof(Elf64_Word), 0, fl); 01133 (void) ir_b_save_buf ((void *) &map_value, // data 01134 sizeof(MAP_ENTRY_TYPE), // size 01135 sizeof(MAP_ENTRY_TYPE), // alignment 01136 0, // padding 01137 fl); // file 01138 } 01139 } 01140 01141 PU_Info_subsect_ptr(pu, subsection_type) = NULL; 01142 01143 free(nodes_represented); 01144 01145 /* write out a -1 to mark the end */ 01146 node_offset = (Elf64_Word)-1; 01147 ir_b_save_buf(&node_offset, sizeof(Elf64_Word), sizeof(Elf64_Word), 0, fl); 01148 01149 Set_PU_Info_state(pu, subsection_type, Subsect_Written); 01150 PU_Info_subsect_size(pu, subsection_type) = fl->file_size - mapping_base; 01151 PU_Info_subsect_offset(pu, subsection_type) = 01152 mapping_base - fl->cur_section->shdr.sh_offset; 01153 } /* WN_write_generic_map */ 01154 01155 01156 void 01157 WN_write_INT32_map(PU_Info *pu, 01158 WN_MAP off_map, 01159 Output_File *fl, 01160 INT32 subsection_type, 01161 WN_MAP value_map, 01162 const char *subsection_name) 01163 { 01164 WN_write_generic_map(pu, off_map, fl, subsection_type, value_map, 01165 subsection_name, (INT32) 0); 01166 } 01167 01168 void 01169 WN_write_voidptr_map(PU_Info *pu, 01170 WN_MAP off_map, 01171 Output_File *fl, 01172 INT32 subsection_type, 01173 WN_MAP value_map, 01174 const char *subsection_name) 01175 { 01176 WN_write_generic_map(pu, off_map, fl, subsection_type, value_map, 01177 subsection_name, (void *) 0); 01178 } 01179 01180 void 01181 IPA_copy_PU (PU_Info *pu, char *section_base, Output_File *outfile) 01182 { 01183 char *subsect; 01184 off_t base; 01185 char buffer [sizeof (WN)]; 01186 WN *dummy = (WN *) &buffer [0];; 01187 INT padding; 01188 Subsect_State state; 01189 01190 /* make sure we're in the right section */ 01191 if (strcmp(outfile->cur_section->name, MIPS_WHIRL_PU_SECTION) != 0) 01192 ErrMsg (EC_IR_Scn_Write, "PU", outfile->file_name); 01193 01194 /* copy the SYMTAB section */ 01195 state = PU_Info_state(pu, WT_SYMTAB); 01196 if (state == Subsect_Exists) 01197 Set_PU_Info_state(pu, WT_SYMTAB, Subsect_Written); 01198 else if (state != Subsect_Written) 01199 ErrMsg (EC_IR_Scn_Write, "symtab", outfile->file_name); 01200 subsect = section_base + PU_Info_subsect_offset(pu, WT_SYMTAB); 01201 outfile->file_size = ir_b_align(outfile->file_size, sizeof(mINT64), 0); 01202 base = outfile->file_size; 01203 ir_b_save_buf(subsect, PU_Info_subsect_size(pu, WT_SYMTAB), 01204 sizeof(mINT64), 0, outfile); 01205 01206 PU_Info_subsect_offset(pu, WT_SYMTAB) = 01207 base - outfile->cur_section->shdr.sh_offset; 01208 01209 /* calculate the padding for the TREE section */ 01210 WN_set_opcode(dummy, OPC_FUNC_ENTRY); 01211 padding = (char *)dummy - (char *)WN_StartAddress(dummy) + 01212 sizeof(Elf64_Word); 01213 01214 /* copy the TREE section */ 01215 state = PU_Info_state(pu, WT_TREE); 01216 if (state == Subsect_Exists) 01217 Set_PU_Info_state(pu, WT_TREE, Subsect_Written); 01218 else if (state != Subsect_Written) 01219 ErrMsg (EC_IR_Scn_Write, "tree", outfile->file_name); 01220 subsect = section_base + PU_Info_subsect_offset(pu, WT_TREE); 01221 outfile->file_size = ir_b_align(outfile->file_size, ALIGNOF(WN), 01222 padding); 01223 base = outfile->file_size; 01224 ir_b_save_buf(subsect, PU_Info_subsect_size(pu, WT_TREE), 01225 ALIGNOF(WN), padding, outfile); 01226 PU_Info_subsect_offset(pu, WT_TREE) = 01227 base - outfile->cur_section->shdr.sh_offset; 01228 01229 /* copy the DEPGRAPH section (optional) */ 01230 state = PU_Info_state(pu, WT_DEPGRAPH); 01231 if (state != Subsect_Missing) { 01232 if (state == Subsect_Exists) 01233 Set_PU_Info_state(pu, WT_DEPGRAPH, Subsect_Written); 01234 else if (state != Subsect_Written) 01235 ErrMsg (EC_IR_Scn_Write, "depgraph", outfile->file_name); 01236 subsect = section_base + PU_Info_subsect_offset(pu, WT_DEPGRAPH); 01237 outfile->file_size = ir_b_align(outfile->file_size, sizeof(mINT32), 0); 01238 base = outfile->file_size; 01239 ir_b_save_buf(subsect, PU_Info_subsect_size(pu, WT_DEPGRAPH), 01240 sizeof(mINT32), 0, outfile); 01241 PU_Info_subsect_offset(pu, WT_DEPGRAPH) = 01242 base - outfile->cur_section->shdr.sh_offset; 01243 } 01244 01245 /* copy the PREFETCH section (optional) */ 01246 state = PU_Info_state(pu, WT_PREFETCH); 01247 if (state != Subsect_Missing) { 01248 if (state == Subsect_Exists) 01249 Set_PU_Info_state(pu, WT_PREFETCH, Subsect_Written); 01250 else if (state != Subsect_Written) 01251 ErrMsg (EC_IR_Scn_Write, "prefetch", outfile->file_name); 01252 subsect = section_base + PU_Info_subsect_offset(pu, WT_PREFETCH); 01253 outfile->file_size = ir_b_align(outfile->file_size, sizeof(mINT32), 0); 01254 base = outfile->file_size; 01255 ir_b_save_buf(subsect, PU_Info_subsect_size(pu, WT_PREFETCH), 01256 sizeof(mINT32), 0, outfile); 01257 PU_Info_subsect_offset(pu, WT_PREFETCH) = 01258 base - outfile->cur_section->shdr.sh_offset; 01259 } 01260 01261 } 01262 01263 #endif /* BACK_END */ 01264 01265 01266 void 01267 WN_write_revision (Output_File *fl) 01268 { 01269 Section *cur_section; 01270 int length = strlen (Whirl_Revision); 01271 01272 cur_section = get_section (0, ELF_COMMENT, fl); 01273 01274 cur_section->shdr.sh_offset = fl->file_size; 01275 01276 ir_b_save_buf (Whirl_Revision, length+1, 0, 0, fl); 01277 01278 cur_section->shdr.sh_size = fl->file_size - cur_section->shdr.sh_offset; 01279 cur_section->shdr.sh_addralign = 1; 01280 /* override the default section type */ 01281 cur_section->shdr.sh_type = SHT_PROGBITS; 01282 01283 } /* write_revision */ 01284 01285 01286 void 01287 WN_close_output (Output_File *fl) 01288 { 01289 if (fl->output_fd < 0) 01290 ErrMsg (EC_IR_Close, fl->file_name, EBADF); 01291 01292 #ifndef __ALWAYS_USE_64BIT_ELF__ 01293 if (Use_32_Bit_Pointers) { 01294 Elf32_Shdr strtab_sec; /* for section string table */ 01295 UINT64 offset = layout_sections (strtab_sec, fl); 01296 01297 // Solaris CC workaround 01298 // write_output() was defined as a template function, now it is not. 01299 write_output (offset, strtab_sec, fl, ELF32()); 01300 } else 01301 #endif 01302 { 01303 Elf64_Shdr strtab_sec; 01304 UINT64 e_shoff = layout_sections (strtab_sec, fl); 01305 write_output (e_shoff, strtab_sec, fl, ELF64()); 01306 } 01307 01308 // eraxxon: unmap output file now for cygwin. cygwin is 01309 // necessarily built upon Win32 which requires all other accesses 01310 // to the file to be closed before it can be changed. 01311 MUNMAP(fl->map_addr, fl->mapped_size); 01312 if (ftruncate(fl->output_fd, fl->file_size) != 0) { 01313 ErrMsg (EC_IR_Close, fl->file_name, errno); 01314 } 01315 01316 close (fl->output_fd); 01317 cleanup (fl); 01318 01319 } /* WN_close_output */ 01320 01321 void 01322 WN_close_file (void *this_fl) 01323 { 01324 Output_File *fl = (Output_File *)this_fl; 01325 if (fl->output_fd < 0) 01326 ErrMsg (EC_IR_Close, fl->file_name, EBADF); 01327 01328 // eraxxon: unmap output file now for cygwin. cygwin is 01329 // necessarily built upon Win32 which requires all other accesses 01330 // to the file to be closed before it can be changed. 01331 MUNMAP(fl->map_addr, fl->mapped_size); 01332 if (ftruncate(fl->output_fd, fl->file_size) != 0) { 01333 ErrMsg (EC_IR_Close, fl->file_name, errno); 01334 } 01335 01336 close (fl->output_fd); 01337 cleanup (fl); 01338 } 01339 01340 01341 #ifndef OWN_ERROR_PACKAGE 01342 01343 /* 01344 * Define common routines for writing all the whirl sections. 01345 * These routines use the standard compiler error reporting mechanism. 01346 */ 01347 01348 static Output_File *ir_output; 01349 01350 void 01351 Write_PU_Info (PU_Info *pu) 01352 { 01353 Temporary_Error_Phase ephase("Writing WHIRL file"); 01354 01355 WN_MAP off_map = WN_MAP_UNDEFINED; 01356 01357 WN_write_symtab (pu, ir_output); 01358 01359 /* create a map to save the file offsets for certain WN nodes */ 01360 #ifdef BACK_END 01361 if (Write_BE_Maps || Write_ALIAS_CLASS_Map) { 01362 Current_Map_Tab = PU_Info_maptab(pu); 01363 MEM_POOL_Push(MEM_local_nz_pool_ptr); 01364 off_map = WN_MAP32_Create(MEM_local_nz_pool_ptr); 01365 } 01366 #endif 01367 01368 WN_write_tree (pu, off_map, ir_output); 01369 01370 #ifdef BACK_END 01371 if (Write_BE_Maps || Write_ALIAS_CLASS_Map) { 01372 01373 if (Write_ALIAS_CLASS_Map) { 01374 WN_write_INT32_map(pu, off_map, ir_output, WT_ALIAS_CLASS, 01375 WN_MAP_ALIAS_CLASS, "alias class map"); 01376 } 01377 01378 WN_MAP_Delete(off_map); 01379 MEM_POOL_Pop(MEM_local_nz_pool_ptr); 01380 } 01381 01382 #endif // BACK_END 01383 01384 } 01385 01386 01387 Output_File * 01388 Open_Output_Info (const char *output_file) 01389 { 01390 Set_Error_Phase ("Writing WHIRL file" ); 01391 ir_output = WN_open_output (output_file); 01392 01393 if (!ir_output) { 01394 ErrMsg (EC_IR_Create, output_file, errno); 01395 } 01396 return ir_output; 01397 } 01398 01399 void 01400 Write_Global_Info (PU_Info *pu_tree) 01401 { 01402 Set_Error_Phase ("Writing WHIRL file" ); 01403 WN_write_PU_Infos (pu_tree, ir_output); 01404 01405 01406 WN_write_globals (ir_output); 01407 01408 WN_write_dst(Current_DST, ir_output); 01409 01410 WN_write_strtab(Index_To_Str (0), STR_Table_Size (), ir_output); 01411 01412 } 01413 01414 void 01415 Close_Output_Info (void) 01416 { 01417 WN_write_revision (ir_output); 01418 01419 WN_close_output(ir_output); 01420 } 01421 01422 01423 #if (defined(linux) || defined(__CYGWIN__)) 01424 extern "C" void 01425 WN_write_elf_symtab (const void* symtab, UINT64 size, UINT64 entsize, 01426 UINT align, Output_File* fl) 01427 { 01428 // create an ELF_STRTAB section that points to MIPS_WHIRL_STRTAB 01429 Section* elf_strtab = get_section (0, ELF_STRTAB, fl); 01430 Section* whirl_strtab = get_section (WT_STRTAB, MIPS_WHIRL_STRTAB, fl); 01431 elf_strtab->shdr = whirl_strtab->shdr; 01432 elf_strtab->shdr.sh_type = SHT_STRTAB; 01433 elf_strtab->shdr.sh_info = 0; 01434 01435 UINT strtab_idx = elf_strtab - fl->section_list + 1; // shdr[0] is always zero 01436 01437 Section* cur_section = get_section (0, ELF_SYMTAB, fl); 01438 01439 fl->file_size = ir_b_align (fl->file_size, align, 0); 01440 cur_section->shdr.sh_offset = fl->file_size; 01441 01442 (void) ir_b_save_buf (symtab, size, align, 0, fl); 01443 01444 cur_section->shdr.sh_type = SHT_SYMTAB; 01445 cur_section->shdr.sh_size = fl->file_size - cur_section->shdr.sh_offset; 01446 cur_section->shdr.sh_addralign = align; 01447 cur_section->shdr.sh_link = strtab_idx; 01448 cur_section->shdr.sh_entsize = entsize; 01449 } // WN_write_elf_symtab 01450 #endif // linux 01451 #endif // OWN_ERROR_PACKAGE 01452 01453 01454 01455