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

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

unix.superglobalmegacorp.com

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