Annotation of GNUtools/cc/bc-emit.c, revision 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.