Annotation of gcc/bc-emit.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.