Annotation of GNUtools/cc/bc-emit.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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