OSDN Git Service

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