00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifdef USE_PCH
00037 #include "common_com_pch.h"
00038 #endif
00039 #pragma hdrstop
00040 #include <unistd.h>
00041 #include <sys/mman.h>
00042 #include <string.h>
00043 #include <errno.h>
00044 #include <elf.h>
00045 #include <sys/elf_whirl.h>
00046
00047
00048
00049 #ifndef USE_STANDARD_TYPES
00050 #define USE_STANDARD_TYPES
00051 #endif
00052
00053 #include "defs.h"
00054 #include "alignof.h"
00055 #include "erglob.h"
00056 #include "errors.h"
00057 #include "opcode.h"
00058 #include "mempool.h"
00059 #include "wn.h"
00060 #include "wn_map.h"
00061 #include "strtab.h"
00062 #include "symtab.h"
00063 #include "irbdata.h"
00064 #define USE_DST_INTERNALS
00065 #include "dwarf_DST_mem.h"
00066 #include "pu_info.h"
00067 #include "ir_bwrite.h"
00068 #include "ir_bcom.h"
00069 #include <vector>
00070
00071
00072 #define MAPPED_SIZE 0x400000
00073 #define INIT_TMP_MAPPED_SIZE MAPPED_SIZE
00074
00075 #ifdef BACK_END
00076 #define DEFAULT_NUM_OF_PREFETCHES 64
00077 WN **prefetch_ldsts;
00078 INT num_prefetch_ldsts;
00079 INT max_num_prefetch_ldsts;
00080
00081 #define DEFAULT_NUM_ALIAS_CLASSES 128
00082 WN **alias_classes;
00083 INT num_alias_class_nodes;
00084 INT max_alias_class_nodes;
00085
00086 #define DEFAULT_NUM_AC_INTERNALS 128
00087 WN **ac_internals;
00088 INT num_ac_internal_nodes;
00089 INT max_ac_internal_nodes;
00090 #endif
00091
00092
00093 char *Whirl_Revision = WHIRL_REVISION;
00094
00095
00096
00097
00098 void *IPAA_Local_Map = NULL;
00099
00100 BOOL Doing_mmapped_io = FALSE;
00101
00102
00103
00104
00105
00106
00107
00108
00109 extern Elf64_Word
00110 ir_b_save_buf (const void *buf, Elf64_Word size, unsigned int align,
00111 unsigned int padding, Output_File *fl)
00112 {
00113 Current_Output = fl;
00114
00115 off_t file_size = ir_b_align (fl->file_size, align, padding);
00116
00117 if (file_size + size >= fl->mapped_size)
00118 ir_b_grow_map (file_size + size - fl->file_size, fl);
00119
00120 Doing_mmapped_io = TRUE;
00121 (void *)memcpy(fl->map_addr + file_size, buf, size);
00122 Doing_mmapped_io = FALSE;
00123
00124 fl->file_size = file_size + size;
00125 return file_size + padding;
00126 }
00127
00128
00129
00130 extern Elf64_Word
00131 ir_b_copy_file (const void *buf, Elf64_Word size, void *tmpfl)
00132 {
00133 Output_File* fl = (Output_File*)tmpfl;
00134
00135 Current_Output = fl;
00136
00137 if (size >= fl->mapped_size)
00138 ir_b_grow_map (size, fl);
00139
00140 Doing_mmapped_io = TRUE;
00141 memcpy (fl->map_addr, buf, size);
00142 Doing_mmapped_io = FALSE;
00143 fl->file_size = size;
00144 return size;
00145 }
00146
00147
00148 static void
00149 save_buf_at_offset (const void *buf, Elf64_Word size, off_t offset,
00150 Output_File *fl)
00151 {
00152 Is_True (offset + size <= fl->mapped_size, ("Invalid buffer size"));
00153
00154 Doing_mmapped_io = TRUE;
00155 memcpy (fl->map_addr + offset, buf, size);
00156 Doing_mmapped_io = FALSE;
00157 }
00158
00159
00160
00161 static Elf64_Word
00162 ir_b_reserve_space (Elf64_Word size, unsigned int align, Output_File *fl)
00163 {
00164 off_t file_size = ir_b_align (fl->file_size, align, 0);
00165
00166 if (file_size + size >= fl->mapped_size)
00167 ir_b_grow_map (file_size + size - fl->file_size, fl);
00168
00169 fl->file_size = file_size + size;
00170 return file_size;
00171 }
00172
00173
00174
00175
00176
00177
00178
00179 char *
00180 ir_b_grow_map (Elf64_Word min_size, Output_File *fl)
00181 {
00182 Is_True (fl->map_addr != 0, ("output file not yet mapped"));
00183
00184 if (munmap (fl->map_addr, fl->mapped_size) == -1)
00185 ErrMsg (EC_IR_Write, fl->file_name, errno);
00186 min_size += fl->file_size;
00187 while (fl->mapped_size < min_size) {
00188 if (fl->mapped_size < MAPPED_SIZE)
00189 fl->mapped_size = MAPPED_SIZE;
00190 else
00191 fl->mapped_size += MAPPED_SIZE;
00192 }
00193
00194 #if defined(__sgi)
00195
00196 fl->map_addr = (char *) mmap (0, fl->mapped_size, PROT_READ|PROT_WRITE,
00197 MAP_SHARED|MAP_AUTOGROW, fl->output_fd, 0);
00198 #else
00199
00200
00201
00202 if (ftruncate(fl->output_fd, fl->mapped_size)) {
00203 ErrMsg (EC_IR_Write, fl->file_name, strerror(errno));
00204 }
00205 fl->map_addr = (char *) mmap (0, fl->mapped_size, PROT_READ|PROT_WRITE,
00206 MAP_SHARED, fl->output_fd, 0);
00207 #endif
00208
00209 if (fl->map_addr == (char *) (-1))
00210 ErrMsg (EC_IR_Write, fl->file_name, strerror(errno));
00211
00212 return fl->map_addr;
00213 }
00214
00215 extern char *
00216 ir_b_create_map (Output_File *fl)
00217 {
00218 int fd = fl->output_fd;
00219 fl->mapped_size = INIT_TMP_MAPPED_SIZE;
00220
00221 #if defined(__sgi)
00222
00223 fl->map_addr = (char *) mmap (0, fl->mapped_size, PROT_READ|PROT_WRITE,
00224 MAP_SHARED|MAP_AUTOGROW, fl->output_fd, 0);
00225 #else
00226 fl->map_addr = (char *) mmap (0, fl->mapped_size, PROT_READ|PROT_WRITE,
00227 MAP_SHARED, fl->output_fd, 0);
00228 #endif
00229
00230 return fl->map_addr;
00231 }
00232
00233
00234 WN *staticNode;
00235
00236
00237 extern Elf64_Word
00238 ir_b_write_tree (WN *node, off_t base_offset, Output_File *fl, WN_MAP off_map)
00239 {
00240 register OPCODE opcode;
00241 Elf64_Word node_offset;
00242 char *real_addr;
00243
00244 if (node == staticNode) abort();
00245
00246 INT32 size = WN_Size_and_StartAddress (node, (void **) &real_addr);
00247
00248 #define WN_ADDR(offset) ((WN *)(fl->map_addr + offset))
00249
00250 node_offset = ir_b_save_buf (real_addr, size, ALIGNOF(WN),
00251 (char *)(node) - real_addr, fl);
00252
00253 opcode = (OPCODE) WN_opcode (node);
00254
00255 #ifdef BACK_END
00256 if (off_map != WN_MAP_UNDEFINED &&
00257 (Write_BE_Maps ||
00258 Write_ALIAS_CLASS_Map ||
00259 Write_AC_INTERNAL_Map)) {
00260
00261 BOOL set_offset = FALSE;
00262 OPERATOR opr = OPCODE_operator(opcode);
00263
00264 if (Write_BE_Maps) {
00265 if (opr == OPR_PREFETCH || opr == OPR_PREFETCHX ||
00266 OPCODE_is_load (opcode) || OPCODE_is_store (opcode))
00267 set_offset = TRUE;
00268
00269
00270 if (WN_MAP_Get(WN_MAP_PREFETCH, node)) {
00271
00272
00273 if (num_prefetch_ldsts == 0) {
00274 max_num_prefetch_ldsts = DEFAULT_NUM_OF_PREFETCHES;
00275 prefetch_ldsts =
00276 (WN **)malloc(max_num_prefetch_ldsts * sizeof(WN*));
00277 FmtAssert (prefetch_ldsts,
00278 ("No more memory for allocation."));
00279 } else if (max_num_prefetch_ldsts == num_prefetch_ldsts + 1) {
00280 max_num_prefetch_ldsts *= 2;
00281 prefetch_ldsts =
00282 (WN **)realloc(prefetch_ldsts,
00283 max_num_prefetch_ldsts * sizeof(WN*));
00284 FmtAssert (prefetch_ldsts,
00285 ("No more memory for allocation."));
00286 }
00287 prefetch_ldsts[num_prefetch_ldsts] = node;
00288 num_prefetch_ldsts += 1;
00289 }
00290 }
00291
00292 if (Write_ALIAS_CLASS_Map) {
00293 if (OPCODE_is_store (opcode) ||
00294 OPCODE_is_load (opcode) ||
00295 (opr == OPR_LDA ) ||
00296 opr == OPR_PARM) {
00297 set_offset = TRUE;
00298 }
00299
00300 if (WN_MAP32_Get (WN_MAP_ALIAS_CLASS, node) != 0) {
00301 if (alias_classes == NULL) {
00302 max_alias_class_nodes = DEFAULT_NUM_ALIAS_CLASSES;
00303 alias_classes = (WN **) malloc (max_alias_class_nodes *
00304 sizeof(WN *));
00305 FmtAssert (alias_classes != NULL, ("No more memory."));
00306 } else if (max_alias_class_nodes == num_alias_class_nodes + 1) {
00307 max_alias_class_nodes *= 2;
00308 alias_classes = (WN **) realloc(alias_classes,
00309 max_alias_class_nodes *
00310 sizeof(WN **));
00311 FmtAssert(alias_classes != NULL, ("No more memory."));
00312 }
00313 alias_classes[num_alias_class_nodes++] = node;
00314 }
00315 }
00316
00317 if (Write_AC_INTERNAL_Map) {
00318 if (opr == OPR_ILOAD ||
00319 opr == OPR_MLOAD ||
00320 opr == OPR_PARM ||
00321 opr == OPR_ISTORE ||
00322 opr == OPR_PSTORE ||
00323 opr == OPR_MSTORE) {
00324 set_offset = TRUE;
00325 }
00326
00327 if (WN_MAP_Get (WN_MAP_AC_INTERNAL, node) != NULL) {
00328 if (ac_internals == NULL) {
00329 max_ac_internal_nodes = DEFAULT_NUM_AC_INTERNALS;
00330 ac_internals = (WN **) malloc (max_ac_internal_nodes *
00331 sizeof(WN *));
00332 FmtAssert (ac_internals != NULL, ("No more memory."));
00333 } else if (max_ac_internal_nodes == num_ac_internal_nodes + 1) {
00334 max_ac_internal_nodes *= 2;
00335 ac_internals = (WN **) realloc(ac_internals,
00336 max_ac_internal_nodes *
00337 sizeof(WN **));
00338 FmtAssert(ac_internals != NULL, ("No more memory."));
00339 }
00340 ac_internals[num_ac_internal_nodes++] = node;
00341 }
00342 }
00343
00344 if (set_offset)
00345 WN_MAP32_Set(off_map, node, node_offset - base_offset);
00346
00347 }
00348 #endif
00349
00350
00351 if (opcode == OPC_BLOCK) {
00352 register Elf64_Word prev, this_node;
00353
00354 if (WN_first(node) == 0) {
00355 WN_first(WN_ADDR(node_offset)) = (WN *) -1;
00356 WN_last(WN_ADDR(node_offset)) = (WN *) -1;
00357 } else {
00358 register WN *wn = WN_first (node);
00359 prev = ir_b_write_tree(wn, base_offset, fl, off_map);
00360 WN_first(WN_ADDR(node_offset)) = (WN *) prev;
00361
00362 while (wn = WN_next(wn)) {
00363 this_node = ir_b_write_tree(wn, base_offset, fl, off_map);
00364
00365 WN_next(WN_ADDR(prev + base_offset)) = (WN *) this_node;
00366 WN_prev(WN_ADDR(this_node + base_offset)) = (WN *) prev;
00367 prev = this_node;
00368 }
00369
00370 WN_last(WN_ADDR(node_offset)) = (WN *) prev;
00371 }
00372 } else if (!OPCODE_is_leaf(opcode)) {
00373 register int i;
00374
00375 for (i = 0; i < WN_kid_count(node); i++) {
00376 register Elf64_Word kid;
00377
00378 if (WN_kid(node, i) == 0) {
00379 WN_kid(WN_ADDR(node_offset), i) = (WN *) -1;
00380 } else {
00381 kid = ir_b_write_tree (WN_kid(node, i), base_offset,
00382 fl, off_map);
00383 WN_kid(WN_ADDR(node_offset), i) = (WN *) kid;
00384 }
00385 }
00386 }
00387
00388 if (OPCODE_has_next_prev(opcode)) {
00389
00390 WN_prev(WN_ADDR(node_offset)) = (WN *) -1;
00391 WN_next(WN_ADDR(node_offset)) = (WN *) -1;
00392 }
00393
00394 return node_offset - base_offset;
00395 }
00396
00397
00398
00399
00400
00401 template <class T>
00402 struct WRITE_TABLE_OP
00403 {
00404 Output_File *fl;
00405
00406 void operator () (UINT, T *t, UINT size) const {
00407 (void) ir_b_save_buf (t, size * sizeof(T), ALIGNOF(T), 0, fl);
00408 }
00409
00410 WRITE_TABLE_OP (Output_File *_fl) : fl (_fl) {}
00411 };
00412
00413
00414 template <class TABLE>
00415 Elf64_Word
00416 write_table (TABLE& fld, off_t base_offset,
00417 Output_File *fl)
00418 {
00419 off_t cur_offset = ir_b_align (fl->file_size,
00420 ALIGNOF(typename TABLE::base_type), 0);
00421 fl->file_size = ir_b_align (fl->file_size,
00422 ALIGNOF(typename TABLE::base_type), 0);
00423
00424 const WRITE_TABLE_OP<typename TABLE::base_type> write_table_op(fl);
00425
00426 For_all_blocks (fld, write_table_op);
00427 return cur_offset - base_offset;
00428 }
00429
00430
00431 static Elf64_Word
00432 write_file_info (off_t base_offset, Output_File *fl)
00433 {
00434 off_t cur_offset = ir_b_align (fl->file_size, ALIGNOF(FILE_INFO), 0);
00435
00436 ir_b_save_buf (&File_info, sizeof(File_info), ALIGNOF(FILE_INFO), 0, fl);
00437
00438 return cur_offset - base_offset;
00439 }
00440
00441
00442
00443 Elf64_Word
00444 ir_b_write_global_symtab (off_t base_offset, Output_File *fl)
00445 {
00446 GLOBAL_SYMTAB_HEADER_TABLE gsymtab;
00447
00448
00449
00450 const Elf64_Word symtab_offset =
00451 ir_b_reserve_space (sizeof(gsymtab), sizeof(mUINT64), fl);
00452
00453 Elf64_Word cur_offset;
00454 UINT i = 0;
00455 const UINT idx = GLOBAL_SYMTAB;
00456
00457 cur_offset = write_file_info (symtab_offset, fl);
00458 gsymtab.header[i++].Init (cur_offset, sizeof(FILE_INFO),
00459 sizeof(FILE_INFO), ALIGNOF(FILE_INFO),
00460 SHDR_FILE);
00461
00462 cur_offset = write_table (*(Scope_tab[idx].st_tab), symtab_offset, fl);
00463 gsymtab.header[i++].Init (cur_offset,
00464 Scope_tab[idx].st_tab->Size () * sizeof(ST),
00465 sizeof(ST), ALIGNOF(ST), SHDR_ST);
00466
00467
00468
00469 cur_offset = write_table (Ty_tab, symtab_offset, fl);
00470 gsymtab.header[i++].Init (cur_offset, Ty_tab.Size () * sizeof(TY),
00471 sizeof(TY), ALIGNOF(TY), SHDR_TY);
00472
00473 cur_offset = write_table (Pu_Table, symtab_offset, fl);
00474 gsymtab.header[i++].Init (cur_offset, Pu_Table.Size () * sizeof(PU),
00475 sizeof(PU), ALIGNOF(PU), SHDR_PU);
00476
00477 cur_offset = write_table (Fld_Table, symtab_offset, fl);
00478 gsymtab.header[i++].Init (cur_offset, Fld_Table.Size () * sizeof(FLD),
00479 sizeof(FLD), ALIGNOF(FLD), SHDR_FLD);
00480
00481 cur_offset = write_table (Arb_Table, symtab_offset, fl);
00482 gsymtab.header[i++].Init (cur_offset, Arb_Table.Size () * sizeof(ARB),
00483 sizeof(ARB), ALIGNOF(ARB), SHDR_ARB);
00484
00485 cur_offset = write_table (Tylist_Table, symtab_offset, fl);
00486 gsymtab.header[i++].Init (cur_offset,
00487 Tylist_Table.Size () * sizeof(TYLIST),
00488 sizeof(TYLIST), ALIGNOF(TYLIST), SHDR_TYLIST);
00489
00490 cur_offset = write_table (Tcon_Table, symtab_offset, fl);
00491 gsymtab.header[i++].Init (cur_offset, Tcon_Table.Size () * sizeof(TCON),
00492 sizeof(TCON), ALIGNOF(TCON), SHDR_TCON);
00493
00494 cur_offset = ir_b_save_buf (TCON_strtab_buffer (), TCON_strtab_size (),
00495 1, 0, fl) - symtab_offset;
00496 gsymtab.header[i++].Init (cur_offset, TCON_strtab_size (), 1, 1, SHDR_STR);
00497
00498 cur_offset = write_table (*(Scope_tab[idx].inito_tab), symtab_offset, fl);
00499 gsymtab.header[i++].Init (cur_offset,
00500 Scope_tab[idx].inito_tab->Size () * sizeof(INITO),
00501 sizeof(INITO), ALIGNOF(INITO), SHDR_INITO);
00502
00503 cur_offset = write_table (Initv_Table, symtab_offset, fl);
00504 gsymtab.header[i++].Init (cur_offset, Initv_Table.Size () * sizeof(INITV),
00505 sizeof(INITV), ALIGNOF(INITV), SHDR_INITV);
00506
00507 cur_offset = write_table (Blk_Table, symtab_offset, fl);
00508 gsymtab.header[i++].Init (cur_offset, Blk_Table.Size () * sizeof(BLK),
00509 sizeof(BLK), ALIGNOF(BLK), SHDR_BLK);
00510
00511 cur_offset = write_table (*(Scope_tab[idx].st_attr_tab), symtab_offset, fl);
00512 gsymtab.header[i++].Init (cur_offset,
00513 Scope_tab[idx].st_attr_tab->Size () * sizeof(ST_ATTR),
00514 sizeof(ST_ATTR), ALIGNOF(ST_ATTR), SHDR_ST_ATTR);
00515
00516 save_buf_at_offset (&gsymtab, sizeof(gsymtab), symtab_offset, fl);
00517
00518 return symtab_offset - base_offset;
00519
00520 }
00521
00522 Elf64_Word
00523 ir_b_write_local_symtab (const SCOPE& pu, off_t base_offset, Output_File *fl)
00524 {
00525
00526 LOCAL_SYMTAB_HEADER_TABLE symtab;
00527
00528 const Elf64_Word symtab_offset =
00529 ir_b_reserve_space (sizeof(symtab), sizeof(mUINT64), fl);
00530
00531 UINT i = 0;
00532 Elf64_Word cur_offset;
00533 cur_offset = write_table (*pu.st_tab, symtab_offset, fl);
00534 symtab.header[i++].Init (cur_offset, pu.st_tab->Size () * sizeof(ST),
00535 sizeof(ST), ALIGNOF(ST), SHDR_ST);
00536
00537 cur_offset = write_table (*pu.label_tab, symtab_offset, fl);
00538 symtab.header[i++].Init (cur_offset, pu.label_tab->Size () * sizeof(LABEL),
00539 sizeof(LABEL), ALIGNOF(LABEL), SHDR_LABEL);
00540
00541 cur_offset = write_table (*pu.preg_tab, symtab_offset, fl);
00542 symtab.header[i++].Init (cur_offset, pu.preg_tab->Size () * sizeof(PREG),
00543 sizeof(PREG), ALIGNOF(PREG), SHDR_PREG);
00544
00545 cur_offset = write_table (*pu.inito_tab, symtab_offset, fl);
00546 symtab.header[i++].Init (cur_offset, pu.inito_tab->Size () * sizeof(INITO),
00547 sizeof(INITO), ALIGNOF(INITO), SHDR_INITO);
00548
00549 cur_offset = write_table (*pu.st_attr_tab, symtab_offset, fl);
00550 symtab.header[i++].Init (cur_offset, pu.st_attr_tab->Size () * sizeof(ST_ATTR),
00551 sizeof(ST_ATTR), ALIGNOF(ST_ATTR), SHDR_ST_ATTR);
00552
00553 save_buf_at_offset (&symtab, sizeof(symtab), symtab_offset, fl);
00554
00555 return symtab_offset - base_offset;
00556
00557 }
00558
00559
00560
00561 extern Elf64_Word
00562 ir_b_write_dst (DST_TYPE dst, off_t base_offset, Output_File *fl)
00563 {
00564 vector<char *> savedOffsets;
00565 Elf64_Word cur_offset;
00566 DST_BLOCK_IDX i;
00567 block_header *dst_blocks;
00568 Current_DST = dst;
00569
00570 dst_blocks = ((DST_Type *)dst)->dst_blocks;
00571 FOREACH_DST_BLOCK(i) {
00572
00573 savedOffsets.push_back(dst_blocks[i].offset);
00574 cur_offset = ir_b_save_buf (dst_blocks[i].offset,
00575 dst_blocks[i].size, ALIGNOF(INT64), 0, fl);
00576 dst_blocks[i].offset = (char*)(cur_offset - base_offset);
00577 }
00578 FOREACH_DST_BLOCK(i) {
00579 cur_offset = ir_b_save_buf
00580 ((char*)&dst_blocks[i], sizeof(block_header),
00581 ALIGNOF(block_header), 0, fl);
00582 }
00583 cur_offset = ir_b_save_buf
00584 ((char*)&((DST_Type *)dst)->last_block_header, sizeof(mINT32),
00585 ALIGNOF(INT32), 0, fl);
00586
00587
00588
00589 FOREACH_DST_BLOCK(i) {
00590 dst_blocks[i].offset = savedOffsets[i];
00591 }
00592
00593 return cur_offset - base_offset;
00594 }
00595
00596
00597