OSDN Git Service

(class_narrowest_mode, byte_mode, word_mode): Add
[pf3gnuchains/gcc-fork.git] / gcc / bc-emit.c
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 extern enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS];
46
47 /* Commonly used modes.  */
48 /* Mode whose width is BITS_PER_UNIT */
49 extern enum machine_mode byte_mode;
50
51 /* Mode whose width is BITS_PER_WORD */
52 extern 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 \f
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 \f
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 \f
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 }