OSDN Git Service

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