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