|
|
1.1 ! root 1: /* Output bytecodes for GNU C-compiler. ! 2: Copyright (C) 1993 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 2, or (at your option) ! 9: any later version. ! 10: ! 11: GNU CC is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU CC; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: ! 21: #include "config.h" ! 22: #include "gvarargs.h" ! 23: #include "machmode.h" ! 24: #include "rtl.h" ! 25: #include "real.h" ! 26: #include "obstack.h" ! 27: #include "bytecode.h" ! 28: #ifdef __GNUC__ ! 29: #include "bytetypes.h" ! 30: #endif ! 31: #include "bc-emit.h" ! 32: #include "bc-opcode.h" ! 33: #include "bc-typecd.h" ! 34: #include "bi-run.h" ! 35: ! 36: #include <stdio.h> ! 37: ! 38: extern char *xmalloc (), *xrealloc (); ! 39: extern void free (); ! 40: ! 41: extern struct obstack *rtl_obstack; ! 42: ! 43: /* Indexed by mode class, gives the narrowest mode for each class. */ ! 44: ! 45: enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS]; ! 46: ! 47: /* Commonly used modes. */ ! 48: /* Mode whose width is BITS_PER_UNIT */ ! 49: enum machine_mode byte_mode; ! 50: ! 51: /* Mode whose width is BITS_PER_WORD */ ! 52: enum machine_mode word_mode; ! 53: ! 54: /* Vector indexed by opcode giving info about the args for each opcode. */ ! 55: static struct arityvec arityvec[] = { ! 56: #include "bc-arity.h" ! 57: }; ! 58: ! 59: /* How to print a symbol name for the assembler. */ ! 60: static void ! 61: prsym (file, s) ! 62: FILE *file; ! 63: char *s; ! 64: { ! 65: if (*s == '*') ! 66: fprintf (file, "%s", s + 1); ! 67: else ! 68: ! 69: #ifdef NAMES_HAVE_UNDERSCORES ! 70: fprintf (file, "_%s", s); ! 71: #else ! 72: fprintf (file, "%s", s); ! 73: #endif ! 74: ! 75: } ! 76: ! 77: /* Maintain a bucket hash table for symbol names. */ ! 78: ! 79: #define HASH_BITS 32 ! 80: #define HASH_SIZE 509 ! 81: ! 82: static struct bc_sym *hashtab[HASH_SIZE]; ! 83: ! 84: static unsigned int ! 85: hash (name) ! 86: char *name; ! 87: { ! 88: unsigned int hash = 0; ! 89: ! 90: while (*name) ! 91: { ! 92: hash = hash << 3 | hash >> HASH_BITS - 3; ! 93: hash += *name++; ! 94: } ! 95: ! 96: return hash % HASH_SIZE; ! 97: } ! 98: ! 99: ! 100: /* Look up the named symbol, creating it if it doesn't exist. */ ! 101: struct bc_sym * ! 102: sym_lookup (name) ! 103: char *name; ! 104: { ! 105: int i; ! 106: struct bc_sym *s; ! 107: ! 108: i = hash (name); ! 109: for (s = hashtab[i]; s; s = s->next) ! 110: if (!strcmp (s->name, name)) ! 111: return s; ! 112: ! 113: s = (struct bc_sym *) xmalloc (sizeof (struct bc_sym)); ! 114: s->name = xmalloc (strlen (name) + 1); ! 115: strcpy (s->name, name); ! 116: s->defined = s->global = s->common = 0; ! 117: s->val = 0; ! 118: s->next = hashtab[i]; ! 119: hashtab[i] = s; ! 120: return s; ! 121: } ! 122: ! 123: ! 124: /* Write out .globl and common symbols to the named file. */ ! 125: static void ! 126: bc_sym_write (file) ! 127: FILE *file; ! 128: { ! 129: int i; ! 130: struct bc_sym *s; ! 131: ! 132: for (i = 0; i < HASH_SIZE; ++i) ! 133: for (s = hashtab[i]; s; s = s->next) ! 134: { ! 135: if (s->global) ! 136: { ! 137: fprintf (file, "\n\t.globl "); ! 138: prsym (file, s->name); ! 139: putc ('\n', file); ! 140: if (s->common) ! 141: { ! 142: fprintf (file, "\n\t.comm "); ! 143: prsym (file, s->name); ! 144: fprintf (file, ", %d\n", s->val); ! 145: } ! 146: } ! 147: else if (s->common) ! 148: { ! 149: fprintf (file, "\n\t.lcomm "); ! 150: prsym (file, s->name); ! 151: fprintf (file, ", %d\n", s->val); ! 152: } ! 153: } ! 154: } ! 155: ! 156: ! 157: ! 158: ! 159: /* Create and initialize a new segment. */ ! 160: static struct bc_seg * ! 161: seg_create () ! 162: { ! 163: struct bc_seg *result; ! 164: ! 165: result = (struct bc_seg *) xmalloc (sizeof (struct bc_seg)); ! 166: result->alloc = 256; ! 167: result->data = xmalloc (result->alloc); ! 168: result->size = 0; ! 169: result->syms = 0; ! 170: result->relocs = 0; ! 171: return result; ! 172: } ! 173: ! 174: ! 175: /* Advance the segment index to the next alignment boundary. */ ! 176: static void ! 177: seg_align (seg, log) ! 178: struct bc_seg *seg; ! 179: int log; ! 180: { ! 181: unsigned int oldsize = seg->size; ! 182: ! 183: seg->size = seg->size + (1 << log) - 1 & ~((1 << log) - 1); ! 184: if (seg->size > seg->alloc) ! 185: { ! 186: while (seg->size > seg->alloc) ! 187: seg->alloc *= 2; ! 188: seg->data = xrealloc (seg->data, seg->alloc); ! 189: } ! 190: bzero (seg->data + oldsize, seg->size - oldsize); ! 191: } ! 192: ! 193: ! 194: /* Append the given data to the given segment. */ ! 195: static void ! 196: seg_data (seg, data, size) ! 197: struct bc_seg *seg; ! 198: char *data; ! 199: unsigned int size; ! 200: { ! 201: if (seg->size + size > seg->alloc) ! 202: { ! 203: while (seg->size + size > seg->alloc) ! 204: seg->alloc *= 2; ! 205: seg->data = xrealloc (seg->data, seg->alloc); ! 206: } ! 207: ! 208: bcopy (data, seg->data + seg->size, size); ! 209: seg->size += size; ! 210: } ! 211: ! 212: ! 213: /* Append a zero-filled skip to the given segment. */ ! 214: static void ! 215: seg_skip (seg, size) ! 216: struct bc_seg *seg; ! 217: unsigned int size; ! 218: { ! 219: if (seg->size + size > seg->alloc) ! 220: { ! 221: while (seg->size + size > seg->alloc) ! 222: seg->alloc *= 2; ! 223: seg->data = xrealloc (seg->data, seg->alloc); ! 224: } ! 225: ! 226: memset (seg->data + seg->size, 0, size); ! 227: seg->size += size; ! 228: } ! 229: ! 230: ! 231: /* Define the given name as the current offset in the given segment. It ! 232: is an error if the name is already defined. Return 0 or 1 indicating ! 233: failure or success respectively. */ ! 234: static int ! 235: seg_defsym (seg, name) ! 236: struct bc_seg *seg; ! 237: char *name; ! 238: { ! 239: struct bc_sym *sym; ! 240: struct bc_segsym *segsym; ! 241: ! 242: sym = sym_lookup (name); ! 243: if (sym->defined) ! 244: return 0; ! 245: ! 246: sym->defined = 1; ! 247: sym->val = seg->size; ! 248: segsym = (struct bc_segsym *) xmalloc (sizeof (struct bc_segsym)); ! 249: segsym->sym = sym; ! 250: segsym->next = seg->syms; ! 251: seg->syms = segsym; ! 252: return 1; ! 253: } ! 254: ! 255: ! 256: /* Generate in seg's data a reference to the given sym, adjusted by ! 257: the given offset. */ ! 258: static void ! 259: seg_refsym (seg, name, offset) ! 260: struct bc_seg *seg; ! 261: char *name; ! 262: int offset; ! 263: { ! 264: struct bc_sym *sym; ! 265: struct bc_segreloc *segreloc; ! 266: ! 267: sym = sym_lookup (name); ! 268: segreloc = (struct bc_segreloc *) xmalloc (sizeof (struct bc_segreloc)); ! 269: segreloc->offset = seg->size; ! 270: segreloc->sym = sym; ! 271: segreloc->next = seg->relocs; ! 272: seg->relocs = segreloc; ! 273: seg_data (seg, (char *) &offset, sizeof offset); ! 274: } ! 275: ! 276: ! 277: /* Concatenate the contents of given segments into the first argument. */ ! 278: static void ! 279: seg_concat (result, seg) ! 280: struct bc_seg *result, *seg; ! 281: { ! 282: unsigned int fix; ! 283: struct bc_segsym *segsym; ! 284: struct bc_segreloc *segreloc; ! 285: ! 286: seg_align (result, MACHINE_SEG_ALIGN); ! 287: fix = result->size; ! 288: seg_data (result, seg->data, seg->size); ! 289: free (seg->data); ! 290: ! 291: /* Go through the symbols and relocs of SEG, adjusting their offsets ! 292: for their new location in RESULT. */ ! 293: if (seg->syms) ! 294: { ! 295: segsym = seg->syms; ! 296: do ! 297: segsym->sym->val += fix; ! 298: while (segsym->next && (segsym = segsym->next)); ! 299: segsym->next = result->syms; ! 300: result->syms = seg->syms; ! 301: } ! 302: if (seg->relocs) ! 303: { ! 304: segreloc = seg->relocs; ! 305: do ! 306: segreloc->offset += fix; ! 307: while (segreloc->next && (segreloc = segreloc->next)); ! 308: segreloc->next = result->relocs; ! 309: result->relocs = seg->relocs; ! 310: } ! 311: ! 312: free ((char *) seg); ! 313: } ! 314: ! 315: /* Write a segment to a file. */ ! 316: static void ! 317: bc_seg_write (seg, file) ! 318: struct bc_seg *seg; ! 319: FILE *file; ! 320: { ! 321: struct bc_segsym *segsym, *nsegsym, *psegsym; ! 322: struct bc_segreloc *segreloc, *nsegreloc, *psegreloc; ! 323: int i, offset, flag; ! 324: ! 325: /* Reverse the list of symbols. */ ! 326: for (psegsym = 0, segsym = seg->syms; segsym; segsym = nsegsym) ! 327: { ! 328: nsegsym = segsym->next; ! 329: segsym->next = psegsym; ! 330: psegsym = segsym; ! 331: } ! 332: seg->syms = psegsym; ! 333: ! 334: /* Reverse the list of relocs. */ ! 335: for (psegreloc = 0, segreloc = seg->relocs; segreloc; segreloc = nsegreloc) ! 336: { ! 337: nsegreloc = segreloc->next; ! 338: segreloc->next = psegreloc; ! 339: psegreloc = segreloc; ! 340: } ! 341: seg->relocs = psegreloc; ! 342: ! 343: /* Output each byte of the segment. */ ! 344: for (i = 0, segsym = seg->syms, segreloc = seg->relocs; i < seg->size; ++i) ! 345: { ! 346: while (segsym && segsym->sym->val == i) ! 347: { ! 348: if (i % 8 != 0) ! 349: putc ('\n', file); ! 350: ! 351: BC_WRITE_SEGSYM (segsym, file); ! 352: segsym = segsym->next; ! 353: flag = 1; ! 354: } ! 355: if (segreloc && segreloc->offset == i) ! 356: { ! 357: if (i % 8 != 0) ! 358: putc ('\n', file); ! 359: ! 360: offset = *(int *) (seg->data + i); ! 361: i += sizeof (int) - 1; ! 362: ! 363: BC_WRITE_RELOC_ENTRY (segreloc, file, offset); ! 364: segreloc = segreloc->next; ! 365: flag = 1; ! 366: } ! 367: else ! 368: { ! 369: if (i % 8 == 0 || flag) ! 370: BC_START_BYTECODE_LINE (file); ! 371: ! 372: BC_WRITE_BYTECODE (i % 8 == 0 || flag ? ' ' : ',', ! 373: seg->data[i] & 0xFF, ! 374: file); ! 375: flag = 0; ! 376: if (i % 8 == 7) ! 377: putc ('\n', file); ! 378: } ! 379: } ! 380: ! 381: /* Paranoia check--we should have visited all syms and relocs during ! 382: the output pass. */ ! 383: ! 384: if (segsym || segreloc) ! 385: abort (); ! 386: } ! 387: ! 388: ! 389: ! 390: /* Text and data segments of the object file in making. */ ! 391: static struct bc_seg *bc_text_seg; ! 392: static struct bc_seg *bc_data_seg; ! 393: ! 394: /* Called before anything else in this module. */ ! 395: void ! 396: bc_initialize () ! 397: { ! 398: int min_class_size[(int) MAX_MODE_CLASS]; ! 399: enum machine_mode mode; ! 400: int i; ! 401: ! 402: bc_init_mode_to_code_map (); ! 403: ! 404: bc_text_seg = seg_create (); ! 405: bc_data_seg = seg_create (); ! 406: ! 407: dconst0 = REAL_VALUE_ATOF ("0", DFmode); ! 408: dconst1 = REAL_VALUE_ATOF ("1", DFmode); ! 409: dconst2 = REAL_VALUE_ATOF ("2", DFmode); ! 410: dconstm1 = REAL_VALUE_ATOF ("-1", DFmode); ! 411: ! 412: /* Find the narrowest mode for each class and compute the word and byte ! 413: modes. */ ! 414: ! 415: for (i = 0; i < (int) MAX_MODE_CLASS; i++) ! 416: min_class_size[i] = 1000; ! 417: ! 418: for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE; ! 419: mode = (enum machine_mode) ((int) mode + 1)) ! 420: { ! 421: if (GET_MODE_SIZE (mode) < min_class_size[(int) GET_MODE_CLASS (mode)]) ! 422: { ! 423: class_narrowest_mode[(int) GET_MODE_CLASS (mode)] = mode; ! 424: min_class_size[(int) GET_MODE_CLASS (mode)] = GET_MODE_SIZE (mode); ! 425: } ! 426: if (GET_MODE_CLASS (mode) == MODE_INT ! 427: && GET_MODE_BITSIZE (mode) == BITS_PER_UNIT) ! 428: byte_mode = mode; ! 429: ! 430: if (GET_MODE_CLASS (mode) == MODE_INT ! 431: && GET_MODE_BITSIZE (mode) == BITS_PER_WORD) ! 432: word_mode = mode; ! 433: } ! 434: } ! 435: ! 436: ! 437: /* External addresses referenced in a function. Rather than trying to ! 438: work relocatable address directly into bytecoded functions (which would ! 439: require us to provide hairy location info and possibly obey alignment ! 440: rules imposed by the architecture) we build an auxilary table of ! 441: pointer constants, and encode just offsets into this table into the ! 442: actual bytecode. */ ! 443: static struct bc_seg *ptrconsts; ! 444: ! 445: /* Trampoline code for the function entry. */ ! 446: struct bc_seg *trampoline; ! 447: ! 448: /* Actual byte code of the function. */ ! 449: struct bc_seg *bytecode; ! 450: ! 451: /* List of labels defined in the function. */ ! 452: struct bc_label *labels; ! 453: ! 454: /* List of label references in the function. */ ! 455: struct bc_labelref *labelrefs; ! 456: ! 457: ! 458: /* Add symbol to pointer table. Return offset into table where ! 459: pointer was stored. The offset usually goes into the bytecode ! 460: stream as a constP literal. */ ! 461: int ! 462: bc_define_pointer (p) ! 463: char *p; ! 464: { ! 465: int offset = ptrconsts->size; ! 466: ! 467: seg_refsym (ptrconsts, p, 0); ! 468: return offset; ! 469: } ! 470: ! 471: ! 472: /* Begin a bytecoded function. */ ! 473: int ! 474: bc_begin_function (name) ! 475: char *name; ! 476: { ! 477: ptrconsts = seg_create (); ! 478: trampoline = seg_create (); ! 479: bytecode = seg_create (); ! 480: return seg_defsym (trampoline, name); ! 481: } ! 482: ! 483: ! 484: /* Force alignment in inline bytecode. */ ! 485: void ! 486: bc_align_bytecode (align) ! 487: int align; ! 488: { ! 489: seg_align (bytecode, align); ! 490: } ! 491: ! 492: ! 493: /* Emit data inline into bytecode. */ ! 494: void ! 495: bc_emit_bytecode_const (data, size) ! 496: char *data; ! 497: unsigned int size; ! 498: { ! 499: if (bytecode) ! 500: seg_data (bytecode, data, size); ! 501: } ! 502: ! 503: ! 504: /* Create a new "bytecode label", to have its value defined later. ! 505: Bytecode labels have nothing to do with the object file symbol table, ! 506: and are purely local to a given bytecoded function. */ ! 507: struct bc_label * ! 508: bc_get_bytecode_label () ! 509: { ! 510: struct bc_label *result; ! 511: ! 512: result = (struct bc_label *) xmalloc (sizeof (struct bc_label)); ! 513: result->defined = 0; ! 514: result->next = labels; ! 515: result->uid = 0; ! 516: labels = result; ! 517: return result; ! 518: } ! 519: ! 520: ! 521: /* Define the given label with the current location counter. */ ! 522: int ! 523: bc_emit_bytecode_labeldef (label) ! 524: struct bc_label *label; ! 525: { ! 526: extern int bc_new_uid (); ! 527: ! 528: if (!label || label->defined) ! 529: return 0; ! 530: ! 531: label->offset = bytecode->size; ! 532: label->defined = 1; ! 533: label->uid = bc_new_uid (); ! 534: ! 535: #ifdef DEBUG_PRINT_CODE ! 536: fprintf (stderr, "$%lx:\n", label); ! 537: #endif ! 538: ! 539: return 1; ! 540: } ! 541: ! 542: ! 543: /* Generate a location-relative reference to the given bytecode label. ! 544: It need not be defined yet; label references will be backpatched later. */ ! 545: void ! 546: bc_emit_bytecode_labelref (label) ! 547: struct bc_label *label; ! 548: { ! 549: struct bc_labelref *labelref; ! 550: static int zero; ! 551: ! 552: labelref = (struct bc_labelref *) xmalloc (sizeof (struct bc_labelref)); ! 553: labelref->label = label; ! 554: labelref->offset = bytecode->size; ! 555: labelref->next = labelrefs; ! 556: labelrefs = labelref; ! 557: ! 558: #ifdef DEBUG_PRINT_CODE ! 559: fprintf (stderr, " $%lx", label); ! 560: #endif ! 561: ! 562: seg_data (bytecode, (char *) &zero, sizeof zero); ! 563: } ! 564: ! 565: ! 566: /* Emit a reference to an external address; generate the reference in the ! 567: ptrconst area, and emit an offset in the bytecode. */ ! 568: void ! 569: bc_emit_code_labelref (name, offset) ! 570: char *name; ! 571: int offset; ! 572: { ! 573: int ptroff; ! 574: ! 575: ptroff = ptrconsts->size / sizeof (char *); ! 576: seg_data (bytecode, (char *) &ptroff, sizeof ptroff); ! 577: seg_refsym (ptrconsts, name, offset); ! 578: ! 579: #ifdef DEBUG_PRINT_CODE ! 580: fprintf (stderr, " [external <%x> %s]", ptroff, name); ! 581: #endif ! 582: } ! 583: ! 584: ! 585: /* Backpatch label references in the byte code, and concatenate the bytecode ! 586: and pointer constant segments to the cumulative text for the object file. ! 587: Return a label name for the pointer constants region. */ ! 588: char * ! 589: bc_end_function () ! 590: { ! 591: int addr; ! 592: struct bc_label *label, *next; ! 593: struct bc_labelref *ref, *nextref; ! 594: char ptrconsts_label[20]; ! 595: static int nlab; ! 596: ! 597: /* Backpatch bytecode label references. */ ! 598: for (ref = labelrefs; ref; ref = ref->next) ! 599: if (ref->label->defined) ! 600: { ! 601: addr = ref->label->offset; ! 602: bcopy (&addr, bytecode->data + ref->offset, sizeof addr); ! 603: } ! 604: ! 605: /* Free the chains of labelrefs and labeldefs. */ ! 606: for (ref = labelrefs; ref; ref = nextref) ! 607: { ! 608: nextref = ref->next; ! 609: free ((char *) ref); ! 610: } ! 611: ! 612: for (label = labels; label; label = next) ! 613: { ! 614: next = label->next; ! 615: free ((char *) label); ! 616: } ! 617: ! 618: seg_concat (trampoline, bytecode); ! 619: seg_align (trampoline, MACHINE_SEG_ALIGN); ! 620: sprintf (ptrconsts_label, "*LP%d", nlab++); ! 621: seg_defsym (trampoline, ptrconsts_label); ! 622: seg_concat (trampoline, ptrconsts); ! 623: seg_concat (bc_text_seg, trampoline); ! 624: ! 625: labels = 0; ! 626: labelrefs = 0; ! 627: trampoline = 0; ! 628: bytecode = 0; ! 629: ptrconsts = 0; ! 630: ! 631: return sym_lookup (ptrconsts_label)->name; ! 632: } ! 633: ! 634: /* Force alignment in const data. */ ! 635: void ! 636: bc_align_const (align) ! 637: int align; ! 638: { ! 639: seg_align (bc_text_seg, align); ! 640: } ! 641: ! 642: /* Emit const data. */ ! 643: void ! 644: bc_emit_const (data, size) ! 645: char *data; ! 646: unsigned int size; ! 647: { ! 648: seg_data (bc_text_seg, data, size); ! 649: } ! 650: ! 651: /* Emit a zero-filled constant skip. */ ! 652: void ! 653: bc_emit_const_skip (size) ! 654: unsigned int size; ! 655: { ! 656: seg_skip (bc_text_seg, size); ! 657: } ! 658: ! 659: /* Emit a label definition in const data. */ ! 660: int ! 661: bc_emit_const_labeldef (name) ! 662: char *name; ! 663: { ! 664: return seg_defsym (bc_text_seg, name); ! 665: } ! 666: ! 667: /* Emit a label reference in const data. */ ! 668: void ! 669: bc_emit_const_labelref (name, offset) ! 670: char *name; ! 671: int offset; ! 672: { ! 673: seg_refsym (bc_text_seg, name, offset); ! 674: } ! 675: ! 676: /* Force alignment in data. */ ! 677: void ! 678: bc_align_data (align) ! 679: int align; ! 680: { ! 681: seg_align (bc_data_seg, align); ! 682: } ! 683: ! 684: /* Emit data. */ ! 685: void ! 686: bc_emit_data (data, size) ! 687: char *data; ! 688: unsigned int size; ! 689: { ! 690: seg_data (bc_data_seg, data, size); ! 691: } ! 692: ! 693: /* Emit a zero-filled data skip. */ ! 694: void ! 695: bc_emit_data_skip (size) ! 696: unsigned int size; ! 697: { ! 698: seg_skip (bc_data_seg, size); ! 699: } ! 700: ! 701: /* Emit label definition in data. */ ! 702: int ! 703: bc_emit_data_labeldef (name) ! 704: char *name; ! 705: { ! 706: return seg_defsym (bc_data_seg, name); ! 707: } ! 708: ! 709: /* Emit label reference in data. */ ! 710: void ! 711: bc_emit_data_labelref (name, offset) ! 712: char *name; ! 713: int offset; ! 714: { ! 715: seg_refsym (bc_data_seg, name, offset); ! 716: } ! 717: ! 718: /* Emit a common block of the given name and size. Note that ! 719: when the .o file is actually written non-global "common" ! 720: blocks will have to be turned into space in the data section. */ ! 721: int ! 722: bc_emit_common (name, size) ! 723: char *name; ! 724: unsigned int size; ! 725: { ! 726: struct bc_sym *sym; ! 727: ! 728: sym = sym_lookup (name); ! 729: if (sym->defined) ! 730: return 0; ! 731: ! 732: sym->defined = 1; ! 733: sym->common = 1; ! 734: sym->val = size; ! 735: return 1; ! 736: } ! 737: ! 738: /* Globalize the given label. */ ! 739: void ! 740: bc_globalize_label (name) ! 741: char *name; ! 742: { ! 743: struct bc_sym *sym; ! 744: ! 745: sym = sym_lookup (name); ! 746: sym->global = 1; ! 747: } ! 748: ! 749: static enum { in_text, in_data } section = in_text; ! 750: ! 751: void ! 752: bc_text () ! 753: { ! 754: section = in_text; ! 755: } ! 756: ! 757: void ! 758: bc_data () ! 759: { ! 760: section = in_data; ! 761: } ! 762: ! 763: void ! 764: bc_align (align) ! 765: int align; ! 766: { ! 767: if (section == in_text) ! 768: bc_align_const (align); ! 769: else ! 770: bc_align_data (align); ! 771: } ! 772: ! 773: void ! 774: bc_emit (data, size) ! 775: char *data; ! 776: unsigned int size; ! 777: { ! 778: if (section == in_text) ! 779: bc_emit_const (data, size); ! 780: else ! 781: bc_emit_data (data, size); ! 782: } ! 783: ! 784: void ! 785: bc_emit_skip (size) ! 786: unsigned int size; ! 787: { ! 788: if (section == in_text) ! 789: bc_emit_const_skip (size); ! 790: else ! 791: bc_emit_data_skip (size); ! 792: } ! 793: ! 794: int ! 795: bc_emit_labeldef (name) ! 796: char *name; ! 797: { ! 798: if (section == in_text) ! 799: return bc_emit_const_labeldef (name); ! 800: else ! 801: return bc_emit_data_labeldef (name); ! 802: } ! 803: ! 804: void ! 805: bc_emit_labelref (name, offset) ! 806: char *name; ! 807: int offset; ! 808: { ! 809: if (section == in_text) ! 810: bc_emit_const_labelref (name, offset); ! 811: else ! 812: bc_emit_data_labelref (name, offset); ! 813: } ! 814: ! 815: void ! 816: bc_write_file (file) ! 817: FILE *file; ! 818: { ! 819: BC_WRITE_FILE (file); ! 820: } ! 821: ! 822: ! 823: /* Allocate a new bytecode rtx. ! 824: If you supply a null BC_LABEL, we generate one. */ ! 825: ! 826: rtx ! 827: bc_gen_rtx (label, offset, bc_label) ! 828: char *label; ! 829: int offset; ! 830: struct bc_label *bc_label; ! 831: { ! 832: rtx r; ! 833: ! 834: if (bc_label == 0) ! 835: bc_label = (struct bc_label *) xmalloc (sizeof (struct bc_label)); ! 836: ! 837: r = gen_rtx (CODE_LABEL, VOIDmode, label, bc_label); ! 838: bc_label->offset = offset; ! 839: ! 840: return r; ! 841: } ! 842: ! 843: ! 844: /* Print bytecode rtx */ ! 845: void ! 846: bc_print_rtl (fp, r) ! 847: FILE *fp; ! 848: rtx r; ! 849: { ! 850: #if 0 /* This needs to get fixed to really work again. */ ! 851: /* BC_WRITE_RTL has a definition ! 852: that doesn't even make sense for this use. */ ! 853: BC_WRITE_RTL (r, fp); ! 854: #endif ! 855: } ! 856: ! 857: ! 858: /* Emit a bytecode, keeping a running tally of the stack depth. */ ! 859: void ! 860: bc_emit_bytecode (bytecode) ! 861: enum bytecode_opcode bytecode; ! 862: { ! 863: char byte; ! 864: int npushes = arityvec[(int) bytecode].noutputs - arityvec[(int) bytecode].ninputs; ! 865: static int prev_lineno = -1; ! 866: ! 867: byte = bytecode; ! 868: ! 869: #ifdef BCDEBUG_PRINT_CODE ! 870: if (lineno != prev_lineno) ! 871: { ! 872: fprintf (stderr, "<line %d>\n", lineno); ! 873: prev_lineno = lineno; ! 874: } ! 875: ! 876: fputs (opcode_name[(unsigned int) bytecode], stderr); ! 877: #endif ! 878: ! 879: /* Due to errors we are often requested to output bytecodes that ! 880: will cause an interpreter stack undeflow when executed. Instead of ! 881: dumping core on such occasions, we omit the bytecode. Erroneous code ! 882: should not be executed, regardless. This makes life much easier, since ! 883: we don't have to deceive ourselves about the known stack depth. */ ! 884: ! 885: bc_emit_bytecode_const (&byte, 1); ! 886: ! 887: if ((stack_depth -= arityvec[(int) bytecode].ninputs) >= 0) ! 888: { ! 889: if ((stack_depth += arityvec[(int) bytecode].noutputs) > max_stack_depth) ! 890: max_stack_depth = stack_depth; ! 891: } ! 892: ! 893: #ifdef VALIDATE_STACK_FOR_BC ! 894: VALIDATE_STACK_FOR_BC (); ! 895: #endif ! 896: } ! 897: ! 898: ! 899: #ifdef BCDEBUG_PRINT_CODE ! 900: #define PRLIT(TYPE, PTR) fprintf (stderr, " [%x]", *(TYPE *) PTR) ! 901: #else ! 902: #define PRLIT(X,Y) ! 903: #endif ! 904: ! 905: /* Emit a complete bytecode instruction, expecting the correct number ! 906: of literal values in the call. First argument is the instruction, the ! 907: remaining arguments are literals of size HOST_WIDE_INT or smaller. */ ! 908: void ! 909: bc_emit_instruction (va_alist) ! 910: va_dcl ! 911: { ! 912: va_list arguments; ! 913: enum bytecode_opcode opcode; ! 914: int nliteral, instruction; ! 915: ! 916: ! 917: va_start (arguments); ! 918: ! 919: /* Emit instruction bytecode */ ! 920: opcode = va_arg (arguments, enum bytecode_opcode); ! 921: bc_emit_bytecode (opcode); ! 922: instruction = (int) opcode; ! 923: ! 924: /* Loop literals and emit as bytecode constants */ ! 925: for (nliteral = 0; nliteral < arityvec[instruction].nliterals; nliteral++) ! 926: { ! 927: HOST_WIDE_INT literal; ! 928: ! 929: switch (arityvec[instruction].literals[nliteral]) ! 930: { ! 931: /* This conditional is a kludge, but it's necessary ! 932: because TYPE might be long long. */ ! 933: #ifdef __GNUC__ ! 934: /* Expand definitions into case statements */ ! 935: #define DEFTYPECODE(CODE, NAME, MODE, TYPE) \ ! 936: case CODE: \ ! 937: { \ ! 938: TYPE temp = va_arg (arguments, TYPE); \ ! 939: bc_emit_bytecode_const ((void *) &temp, sizeof temp); \ ! 940: PRLIT (TYPE, &temp); } \ ! 941: break; ! 942: ! 943: #include "bc-typecd.def" ! 944: ! 945: #undef DEFTYPECODE ! 946: #endif /* __GNUC__ */ ! 947: ! 948: default: ! 949: abort (); ! 950: } ! 951: } ! 952: ! 953: #ifdef BCDEBUG_PRINT_CODE ! 954: fputc ('\n', stderr); ! 955: #endif ! 956: } ! 957: ! 958: /* Emit the machine-code interface trampoline at the beginning of a byte ! 959: coded function. The argument is a label name of the interpreter ! 960: bytecode callinfo structure; the return value is a label name for ! 961: the beginning of the actual bytecode. */ ! 962: char * ! 963: bc_emit_trampoline (callinfo) ! 964: char *callinfo; ! 965: { ! 966: char mylab[20]; ! 967: static int n; ! 968: ! 969: sprintf (mylab, "*LB%d", n++); ! 970: ! 971: BC_EMIT_TRAMPOLINE (trampoline, callinfo); ! 972: ! 973: seg_defsym (bytecode, mylab); ! 974: return sym_lookup (mylab)->name; ! 975: } ! 976: ! 977: ! 978: /* Simple strdup */ ! 979: char * ! 980: bc_xstrdup (str) ! 981: char *str; ! 982: { ! 983: char *tmp = xmalloc (strlen (str) + 1); ! 984: ! 985: strcpy (tmp, str); ! 986: return tmp; ! 987: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.