source: trunk/third/gcc/bc-emit.c @ 11288

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