source: trunk/third/gcc/genemit.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/* Generate code from machine description to emit insns as rtl.
2   Copyright (C) 1987, 88, 91, 94, 95, 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 <stdio.h>
23#include "hconfig.h"
24#include "rtl.h"
25#include "obstack.h"
26
27static struct obstack obstack;
28struct obstack *rtl_obstack = &obstack;
29
30#define obstack_chunk_alloc xmalloc
31#define obstack_chunk_free free
32
33extern void free ();
34extern rtx read_rtx ();
35
36char *xmalloc ();
37static void fatal ();
38void fancy_abort ();
39
40static int max_opno;
41static int max_dup_opno;
42static int register_constraints;
43static int insn_code_number;
44static int insn_index_number;
45
46/* Data structure for recording the patterns of insns that have CLOBBERs.
47   We use this to output a function that adds these CLOBBERs to a
48   previously-allocated PARALLEL expression.  */
49
50struct clobber_pat
51{
52  struct clobber_ent *insns;
53  rtx pattern;
54  int first_clobber;
55  struct clobber_pat *next;
56} *clobber_list;
57
58/* Records one insn that uses the clobber list.  */
59
60struct clobber_ent
61{
62  int code_number;              /* Counts only insns.  */
63  struct clobber_ent *next;
64};
65
66static void
67max_operand_1 (x)
68     rtx x;
69{
70  register RTX_CODE code;
71  register int i;
72  register int len;
73  register char *fmt;
74
75  if (x == 0)
76    return;
77
78  code = GET_CODE (x);
79
80  if (code == MATCH_OPERAND && XSTR (x, 2) != 0 && *XSTR (x, 2) != '\0')
81    register_constraints = 1;
82  if (code == MATCH_SCRATCH && XSTR (x, 1) != 0 && *XSTR (x, 1) != '\0')
83    register_constraints = 1;
84  if (code == MATCH_OPERAND || code == MATCH_OPERATOR
85      || code == MATCH_PARALLEL)
86    max_opno = MAX (max_opno, XINT (x, 0));
87  if (code == MATCH_DUP || code == MATCH_OP_DUP || code == MATCH_PAR_DUP)
88    max_dup_opno = MAX (max_dup_opno, XINT (x, 0));
89
90  fmt = GET_RTX_FORMAT (code);
91  len = GET_RTX_LENGTH (code);
92  for (i = 0; i < len; i++)
93    {
94      if (fmt[i] == 'e' || fmt[i] == 'u')
95        max_operand_1 (XEXP (x, i));
96      else if (fmt[i] == 'E')
97        {
98          int j;
99          for (j = 0; j < XVECLEN (x, i); j++)
100            max_operand_1 (XVECEXP (x, i, j));
101        }
102    }
103}
104
105static int
106max_operand_vec (insn, arg)
107     rtx insn;
108     int arg;
109{
110  register int len = XVECLEN (insn, arg);
111  register int i;
112
113  max_opno = -1;
114  max_dup_opno = -1;
115
116  for (i = 0; i < len; i++)
117    max_operand_1 (XVECEXP (insn, arg, i));
118
119  return max_opno + 1;
120}
121
122static void
123print_code (code)
124     RTX_CODE code;
125{
126  register char *p1;
127  for (p1 = GET_RTX_NAME (code); *p1; p1++)
128    {
129      if (*p1 >= 'a' && *p1 <= 'z')
130        putchar (*p1 + 'A' - 'a');
131      else
132        putchar (*p1);
133    }
134}
135
136/* Print a C expression to construct an RTX just like X,
137   substituting any operand references appearing within.  */
138
139static void
140gen_exp (x)
141     rtx x;
142{
143  register RTX_CODE code;
144  register int i;
145  register int len;
146  register char *fmt;
147
148  if (x == 0)
149    {
150      printf ("NULL_RTX");
151      return;
152    }
153
154  code = GET_CODE (x);
155
156  switch (code)
157    {
158    case MATCH_OPERAND:
159    case MATCH_DUP:
160      printf ("operand%d", XINT (x, 0));
161      return;
162
163    case MATCH_OP_DUP:
164      printf ("gen_rtx (GET_CODE (operand%d), GET_MODE (operand%d)",
165              XINT (x, 0), XINT (x, 0));
166      for (i = 0; i < XVECLEN (x, 1); i++)
167        {
168          printf (",\n\t\t");
169          gen_exp (XVECEXP (x, 1, i));
170        }
171      printf (")");
172      return;
173
174    case MATCH_OPERATOR:
175      printf ("gen_rtx (GET_CODE (operand%d)", XINT (x, 0));
176      printf (", %smode", GET_MODE_NAME (GET_MODE (x)));
177      for (i = 0; i < XVECLEN (x, 2); i++)
178        {
179          printf (",\n\t\t");
180          gen_exp (XVECEXP (x, 2, i));
181        }
182      printf (")");
183      return;
184
185    case MATCH_PARALLEL:
186    case MATCH_PAR_DUP:
187      printf ("operand%d", XINT (x, 0));
188      return;
189
190    case MATCH_SCRATCH:
191      printf ("gen_rtx (SCRATCH, %smode, 0)", GET_MODE_NAME (GET_MODE (x)));
192      return;
193
194    case ADDRESS:
195      fatal ("ADDRESS expression code used in named instruction pattern");
196
197    case PC:
198      printf ("pc_rtx");
199      return;
200
201    case CC0:
202      printf ("cc0_rtx");
203      return;
204
205    case CONST_INT:
206      if (INTVAL (x) == 0)
207        printf ("const0_rtx");
208      else if (INTVAL (x) == 1)
209        printf ("const1_rtx");
210      else if (INTVAL (x) == -1)
211        printf ("constm1_rtx");
212      else if (INTVAL (x) == STORE_FLAG_VALUE)
213        printf ("const_true_rtx");
214      else
215        printf (
216#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT     
217                "GEN_INT (%d)",
218#else
219                "GEN_INT (%ld)",
220#endif
221                INTVAL (x));
222      return;
223
224    case CONST_DOUBLE:
225      /* These shouldn't be written in MD files.  Instead, the appropriate
226         routines in varasm.c should be called.  */
227      abort ();
228    }
229
230  printf ("gen_rtx (");
231  print_code (code);
232  printf (", %smode", GET_MODE_NAME (GET_MODE (x)));
233
234  fmt = GET_RTX_FORMAT (code);
235  len = GET_RTX_LENGTH (code);
236  for (i = 0; i < len; i++)
237    {
238      if (fmt[i] == '0')
239        break;
240      printf (",\n\t");
241      if (fmt[i] == 'e' || fmt[i] == 'u')
242        gen_exp (XEXP (x, i));
243      else if (fmt[i] == 'i')
244        printf ("%u", XINT (x, i));
245      else if (fmt[i] == 's')
246        printf ("\"%s\"", XSTR (x, i));
247      else if (fmt[i] == 'E')
248        {
249          int j;
250          printf ("gen_rtvec (%d", XVECLEN (x, i));
251          for (j = 0; j < XVECLEN (x, i); j++)
252            {
253              printf (",\n\t\t");
254              gen_exp (XVECEXP (x, i, j));
255            }
256          printf (")");
257        }
258      else
259        abort ();
260    }
261  printf (")");
262
263
264/* Generate the `gen_...' function for a DEFINE_INSN.  */
265
266static void
267gen_insn (insn)
268     rtx insn;
269{
270  int operands;
271  register int i;
272
273  /* See if the pattern for this insn ends with a group of CLOBBERs of (hard)
274     registers or MATCH_SCRATCHes.  If so, store away the information for
275     later.  */
276
277  if (XVEC (insn, 1))
278    {
279      for (i = XVECLEN (insn, 1) - 1; i > 0; i--)
280        if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER
281            || (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != REG
282                && GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH))
283          break;
284
285      if (i != XVECLEN (insn, 1) - 1)
286        {
287          register struct clobber_pat *p;
288          register struct clobber_ent *link
289            = (struct clobber_ent *) xmalloc (sizeof (struct clobber_ent));
290          register int j;
291
292          link->code_number = insn_code_number;
293
294          /* See if any previous CLOBBER_LIST entry is the same as this
295             one.  */
296
297          for (p = clobber_list; p; p = p->next)
298            {
299              if (p->first_clobber != i + 1
300                  || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1))
301                continue;
302
303              for (j = i + 1; j < XVECLEN (insn, 1); j++)
304                {
305                  rtx old = XEXP (XVECEXP (p->pattern, 1, j), 0);
306                  rtx new = XEXP (XVECEXP (insn, 1, j), 0);
307
308                  /* OLD and NEW are the same if both are to be a SCRATCH
309                     of the same mode,
310                     or if both are registers of the same mode and number.  */
311                  if (! (GET_MODE (old) == GET_MODE (new)
312                         && ((GET_CODE (old) == MATCH_SCRATCH
313                              && GET_CODE (new) == MATCH_SCRATCH)
314                             || (GET_CODE (old) == REG && GET_CODE (new) == REG
315                                 && REGNO (old) == REGNO (new)))))
316                    break;
317                }
318     
319              if (j == XVECLEN (insn, 1))
320                break;
321            }
322
323          if (p == 0)
324            {
325              p = (struct clobber_pat *) xmalloc (sizeof (struct clobber_pat));
326         
327              p->insns = 0;
328              p->pattern = insn;
329              p->first_clobber = i + 1;
330              p->next = clobber_list;
331              clobber_list = p;
332            }
333
334          link->next = p->insns;
335          p->insns = link;
336        }
337    }
338
339  /* Don't mention instructions whose names are the null string
340     or begin with '*'.  They are in the machine description just
341     to be recognized.  */
342  if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*')
343    return;
344
345  /* Find out how many operands this function has,
346     and also whether any of them have register constraints.  */
347  register_constraints = 0;
348  operands = max_operand_vec (insn, 1);
349  if (max_dup_opno >= operands)
350    fatal ("match_dup operand number has no match_operand");
351
352  /* Output the function name and argument declarations.  */
353  printf ("rtx\ngen_%s (", XSTR (insn, 0));
354  for (i = 0; i < operands; i++)
355    printf (i ? ", operand%d" : "operand%d", i);
356  printf (")\n");
357  for (i = 0; i < operands; i++)
358    printf ("     rtx operand%d;\n", i);
359  printf ("{\n");
360
361  /* Output code to construct and return the rtl for the instruction body */
362
363  if (XVECLEN (insn, 1) == 1)
364    {
365      printf ("  return ");
366      gen_exp (XVECEXP (insn, 1, 0));
367      printf (";\n}\n\n");
368    }
369  else
370    {
371      printf ("  return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (%d", XVECLEN (insn, 1));
372      for (i = 0; i < XVECLEN (insn, 1); i++)
373        {
374          printf (",\n\t\t");
375          gen_exp (XVECEXP (insn, 1, i));
376        }
377      printf ("));\n}\n\n");
378    }
379}
380
381/* Generate the `gen_...' function for a DEFINE_EXPAND.  */
382
383static void
384gen_expand (expand)
385     rtx expand;
386{
387  int operands;
388  register int i;
389
390  if (strlen (XSTR (expand, 0)) == 0)
391    fatal ("define_expand lacks a name");
392  if (XVEC (expand, 1) == 0)
393    fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0));
394
395  /* Find out how many operands this function has,
396     and also whether any of them have register constraints.  */
397  register_constraints = 0;
398
399  operands = max_operand_vec (expand, 1);
400
401  /* Output the function name and argument declarations.  */
402  printf ("rtx\ngen_%s (", XSTR (expand, 0));
403  for (i = 0; i < operands; i++)
404    printf (i ? ", operand%d" : "operand%d", i);
405  printf (")\n");
406  for (i = 0; i < operands; i++)
407    printf ("     rtx operand%d;\n", i);
408  printf ("{\n");
409
410  /* If we don't have any C code to write, only one insn is being written,
411     and no MATCH_DUPs are present, we can just return the desired insn
412     like we do for a DEFINE_INSN.  This saves memory.  */
413  if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0')
414      && operands > max_dup_opno
415      && XVECLEN (expand, 1) == 1)
416    {
417      printf ("  return ");
418      gen_exp (XVECEXP (expand, 1, 0));
419      printf (";\n}\n\n");
420      return;
421    }
422
423  /* For each operand referred to only with MATCH_DUPs,
424     make a local variable.  */
425  for (i = operands; i <= max_dup_opno; i++)
426    printf ("  rtx operand%d;\n", i);
427  if (operands > 0 || max_dup_opno >= 0)
428    printf ("  rtx operands[%d];\n", MAX (operands, max_dup_opno + 1));
429  printf ("  rtx _val = 0;\n");
430  printf ("  start_sequence ();\n");
431
432  /* The fourth operand of DEFINE_EXPAND is some code to be executed
433     before the actual construction.
434     This code expects to refer to `operands'
435     just as the output-code in a DEFINE_INSN does,
436     but here `operands' is an automatic array.
437     So copy the operand values there before executing it.  */
438  if (XSTR (expand, 3) && *XSTR (expand, 3))
439    {
440      /* Output code to copy the arguments into `operands'.  */
441      for (i = 0; i < operands; i++)
442        printf ("  operands[%d] = operand%d;\n", i, i);
443
444      /* Output the special code to be executed before the sequence
445         is generated.  */
446      printf ("%s\n", XSTR (expand, 3));
447
448      /* Output code to copy the arguments back out of `operands'
449         (unless we aren't going to use them at all).  */
450      if (XVEC (expand, 1) != 0)
451        {
452          for (i = 0; i < operands; i++)
453            printf ("  operand%d = operands[%d];\n", i, i);
454          for (; i <= max_dup_opno; i++)
455            printf ("  operand%d = operands[%d];\n", i, i);
456        }
457    }
458
459  /* Output code to construct the rtl for the instruction bodies.
460     Use emit_insn to add them to the sequence being accumulated.
461     But don't do this if the user's code has set `no_more' nonzero.  */
462
463  for (i = 0; i < XVECLEN (expand, 1); i++)
464    {
465      rtx next = XVECEXP (expand, 1, i);
466      if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
467          || (GET_CODE (next) == PARALLEL
468              && GET_CODE (XVECEXP (next, 0, 0)) == SET
469              && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
470          || GET_CODE (next) == RETURN)
471        printf ("  emit_jump_insn (");
472      else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
473               || GET_CODE (next) == CALL
474               || (GET_CODE (next) == PARALLEL
475                   && GET_CODE (XVECEXP (next, 0, 0)) == SET
476                   && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
477               || (GET_CODE (next) == PARALLEL
478                   && GET_CODE (XVECEXP (next, 0, 0)) == CALL))
479        printf ("  emit_call_insn (");
480      else if (GET_CODE (next) == CODE_LABEL)
481        printf ("  emit_label (");
482      else if (GET_CODE (next) == MATCH_OPERAND
483               || GET_CODE (next) == MATCH_OPERATOR
484               || GET_CODE (next) == MATCH_PARALLEL
485               || GET_CODE (next) == MATCH_OP_DUP
486               || GET_CODE (next) == MATCH_DUP
487               || GET_CODE (next) == PARALLEL)
488        printf ("  emit (");
489      else
490        printf ("  emit_insn (");
491      gen_exp (next);
492      printf (");\n");
493      if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
494          && GET_CODE (SET_SRC (next)) == LABEL_REF)
495        printf ("  emit_barrier ();");
496    }
497
498  /* Call `gen_sequence' to make a SEQUENCE out of all the
499     insns emitted within this gen_... function.  */
500
501  printf (" _done:\n");
502  printf ("  _val = gen_sequence ();\n");
503  printf (" _fail:\n");
504  printf ("  end_sequence ();\n");
505  printf ("  return _val;\n}\n\n");
506}
507
508/* Like gen_expand, but generates a SEQUENCE.  */
509
510static void
511gen_split (split)
512     rtx split;
513{
514  register int i;
515  int operands;
516
517  if (XVEC (split, 0) == 0)
518    fatal ("define_split (definition %d) lacks a pattern", insn_index_number);
519  else if (XVEC (split, 2) == 0)
520    fatal ("define_split (definition %d) lacks a replacement pattern",
521           insn_index_number);
522
523  /* Find out how many operands this function has.  */
524
525  max_operand_vec (split, 2);
526  operands = MAX (max_opno, max_dup_opno) + 1;
527
528  /* Output the function name and argument declarations.  */
529  printf ("rtx\ngen_split_%d (operands)\n     rtx *operands;\n",
530          insn_code_number);
531  printf ("{\n");
532
533  /* Declare all local variables.  */
534  for (i = 0; i < operands; i++)
535    printf ("  rtx operand%d;\n", i);
536  printf ("  rtx _val = 0;\n");
537  printf ("  start_sequence ();\n");
538
539  /* The fourth operand of DEFINE_SPLIT is some code to be executed
540     before the actual construction.  */
541
542  if (XSTR (split, 3))
543    printf ("%s\n", XSTR (split, 3));
544
545  /* Output code to copy the arguments back out of `operands'  */
546  for (i = 0; i < operands; i++)
547    printf ("  operand%d = operands[%d];\n", i, i);
548
549  /* Output code to construct the rtl for the instruction bodies.
550     Use emit_insn to add them to the sequence being accumulated.
551     But don't do this if the user's code has set `no_more' nonzero.  */
552
553  for (i = 0; i < XVECLEN (split, 2); i++)
554    {
555      rtx next = XVECEXP (split, 2, i);
556      if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
557          || (GET_CODE (next) == PARALLEL
558              && GET_CODE (XVECEXP (next, 0, 0)) == SET
559              && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
560          || GET_CODE (next) == RETURN)
561        printf ("  emit_jump_insn (");
562      else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
563               || GET_CODE (next) == CALL
564               || (GET_CODE (next) == PARALLEL
565                   && GET_CODE (XVECEXP (next, 0, 0)) == SET
566                   && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
567               || (GET_CODE (next) == PARALLEL
568                   && GET_CODE (XVECEXP (next, 0, 0)) == CALL))
569        printf ("  emit_call_insn (");
570      else if (GET_CODE (next) == CODE_LABEL)
571        printf ("  emit_label (");
572      else if (GET_CODE (next) == MATCH_OPERAND
573               || GET_CODE (next) == MATCH_OPERATOR
574               || GET_CODE (next) == MATCH_PARALLEL
575               || GET_CODE (next) == MATCH_OP_DUP
576               || GET_CODE (next) == MATCH_DUP
577               || GET_CODE (next) == PARALLEL)
578        printf ("  emit (");
579      else
580        printf ("  emit_insn (");
581      gen_exp (next);
582      printf (");\n");
583      if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
584          && GET_CODE (SET_SRC (next)) == LABEL_REF)
585        printf ("  emit_barrier ();");
586    }
587
588  /* Call `gen_sequence' to make a SEQUENCE out of all the
589     insns emitted within this gen_... function.  */
590
591  printf (" _done:\n");
592  printf ("  _val = gen_sequence ();\n");
593  printf (" _fail:\n");
594  printf ("  end_sequence ();\n");
595  printf ("  return _val;\n}\n\n");
596}
597
598/* Write a function, `add_clobbers', that is given a PARALLEL of sufficient
599   size for the insn and an INSN_CODE, and inserts the required CLOBBERs at
600   the end of the vector.  */
601
602static void
603output_add_clobbers ()
604{
605  struct clobber_pat *clobber;
606  struct clobber_ent *ent;
607  int i;
608
609  printf ("\n\nvoid\nadd_clobbers (pattern, insn_code_number)\n");
610  printf ("     rtx pattern;\n     int insn_code_number;\n");
611  printf ("{\n");
612  printf ("  int i;\n\n");
613  printf ("  switch (insn_code_number)\n");
614  printf ("    {\n");
615
616  for (clobber = clobber_list; clobber; clobber = clobber->next)
617    {
618      for (ent = clobber->insns; ent; ent = ent->next)
619        printf ("    case %d:\n", ent->code_number);
620
621      for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++)
622        {
623          printf ("      XVECEXP (pattern, 0, %d) = ", i);
624          gen_exp (XVECEXP (clobber->pattern, 1, i));
625          printf (";\n");
626        }
627
628      printf ("      break;\n\n");
629    }
630
631  printf ("    default:\n");
632  printf ("      abort ();\n");
633  printf ("    }\n");
634  printf ("}\n");
635}
636
637/* Write a function, init_mov_optab, that is called to set up entries
638   in mov_optab for EXTRA_CC_MODES.  */
639
640static void
641output_init_mov_optab ()
642{
643#ifdef EXTRA_CC_NAMES
644  static char *cc_names[] = { EXTRA_CC_NAMES };
645  char *p;
646  int i;
647
648  printf ("\nvoid\ninit_mov_optab ()\n{\n");
649
650  for (i = 0; i < sizeof cc_names / sizeof cc_names[0]; i++)
651    {
652      printf ("#ifdef HAVE_mov");
653      for (p = cc_names[i]; *p; p++)
654        printf ("%c", *p >= 'A' && *p <= 'Z' ? *p - 'A' + 'a' : *p);
655      printf ("\n");
656      printf ("  if (HAVE_mov");
657      for (p = cc_names[i]; *p; p++)
658        printf ("%c", *p >= 'A' && *p <= 'Z' ? *p - 'A' + 'a' : *p);
659      printf (")\n");
660      printf ("    mov_optab->handlers[(int) %smode].insn_code = CODE_FOR_mov",
661              cc_names[i]);
662      for (p = cc_names[i]; *p; p++)
663        printf ("%c", *p >= 'A' && *p <= 'Z' ? *p - 'A' + 'a' : *p);
664      printf (";\n#endif\n");
665    }
666
667  printf ("}\n");
668#endif
669}
670
671char *
672xmalloc (size)
673     unsigned size;
674{
675  register char *val = (char *) malloc (size);
676
677  if (val == 0)
678    fatal ("virtual memory exhausted");
679
680  return val;
681}
682
683char *
684xrealloc (ptr, size)
685     char *ptr;
686     unsigned size;
687{
688  char *result = (char *) realloc (ptr, size);
689  if (!result)
690    fatal ("virtual memory exhausted");
691  return result;
692}
693
694static void
695fatal (s, a1, a2)
696     char *s;
697{
698  fprintf (stderr, "genemit: ");
699  fprintf (stderr, s, a1, a2);
700  fprintf (stderr, "\n");
701  exit (FATAL_EXIT_CODE);
702}
703
704/* More 'friendly' abort that prints the line and file.
705   config.h can #define abort fancy_abort if you like that sort of thing.  */
706
707void
708fancy_abort ()
709{
710  fatal ("Internal gcc abort.");
711}
712
713int
714main (argc, argv)
715     int argc;
716     char **argv;
717{
718  rtx desc;
719  FILE *infile;
720  register int c;
721
722  obstack_init (rtl_obstack);
723
724  if (argc <= 1)
725    fatal ("No input file name.");
726
727  infile = fopen (argv[1], "r");
728  if (infile == 0)
729    {
730      perror (argv[1]);
731      exit (FATAL_EXIT_CODE);
732    }
733
734  init_rtl ();
735
736  /* Assign sequential codes to all entries in the machine description
737     in parallel with the tables in insn-output.c.  */
738
739  insn_code_number = 0;
740  insn_index_number = 0;
741
742  printf ("/* Generated automatically by the program `genemit'\n\
743from the machine description file `md'.  */\n\n");
744
745  printf ("#include \"config.h\"\n");
746  printf ("#include <stdio.h>\n");
747  printf ("#include \"rtl.h\"\n");
748  printf ("#include \"expr.h\"\n");
749  printf ("#include \"real.h\"\n");
750  printf ("#include \"flags.h\"\n");
751  printf ("#include \"output.h\"\n");
752  printf ("#include \"insn-config.h\"\n\n");
753  printf ("#include \"insn-flags.h\"\n\n");
754  printf ("#include \"insn-codes.h\"\n\n");
755  printf ("extern char *insn_operand_constraint[][MAX_RECOG_OPERANDS];\n\n");
756  printf ("extern rtx recog_operand[];\n");
757  printf ("#define operands emit_operand\n\n");
758  printf ("#define FAIL goto _fail\n\n");
759  printf ("#define DONE goto _done\n\n");
760
761  /* Read the machine description.  */
762
763  while (1)
764    {
765      c = read_skip_spaces (infile);
766      if (c == EOF)
767        break;
768      ungetc (c, infile);
769
770      desc = read_rtx (infile);
771      if (GET_CODE (desc) == DEFINE_INSN)
772        {
773          gen_insn (desc);
774          ++insn_code_number;
775        }
776      if (GET_CODE (desc) == DEFINE_EXPAND)
777        {
778          gen_expand (desc);
779          ++insn_code_number;
780        }
781      if (GET_CODE (desc) == DEFINE_SPLIT)
782        {
783          gen_split (desc);
784          ++insn_code_number;
785        }
786      if (GET_CODE (desc) == DEFINE_PEEPHOLE)
787        {
788          ++insn_code_number;
789        }
790      ++insn_index_number;
791    }
792
793  /* Write out the routine to add CLOBBERs to a pattern.  */
794  output_add_clobbers ();
795
796  /* Write the routine to initialize mov_optab for the EXTRA_CC_MODES.  */
797  output_init_mov_optab ();
798
799  fflush (stdout);
800  exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
801  /* NOTREACHED */
802  return 0;
803}
Note: See TracBrowser for help on using the repository browser.