OSDN Git Service

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