Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
ir_bwrite.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 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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines