source: trunk/third/gcc/genemit.c @ 8834

Revision 8834, 20.9 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r8833, 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, 1988, 1991, 1994, 1995 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.  */
509static void
510gen_split (split)
511     rtx split;
512{
513  register int i;
514  int operands;
515
516  if (XVEC (split, 0) == 0)
517    fatal ("define_split (definition %d) lacks a pattern", insn_index_number);
518  else if (XVEC (split, 2) == 0)
519    fatal ("define_split (definition %d) lacks a replacement pattern",
520           insn_index_number);
521
522  /* Find out how many operands this function has.  */
523
524  max_operand_vec (split, 2);
525  operands = MAX (max_opno, max_dup_opno) + 1;
526
527  /* Output the function name and argument declarations.  */
528  printf ("rtx\ngen_split_%d (operands)\n     rtx *operands;\n",
529          insn_code_number);
530  printf ("{\n");
531
532  /* Declare all local variables.  */
533  for (i = 0; i < operands; i++)
534    printf ("  rtx operand%d;\n", i);
535  printf ("  rtx _val = 0;\n");
536  printf ("  start_sequence ();\n");
537
538  /* The fourth operand of DEFINE_SPLIT is some code to be executed
539     before the actual construction.  */
540
541  if (XSTR (split, 3))
542    printf ("%s\n", XSTR (split, 3));
543
544  /* Output code to copy the arguments back out of `operands'  */
545  for (i = 0; i < operands; i++)
546    printf ("  operand%d = operands[%d];\n", i, i);
547
548  /* Output code to construct the rtl for the instruction bodies.
549     Use emit_insn to add them to the sequence being accumulated.
550     But don't do this if the user's code has set `no_more' nonzero.  */
551
552  for (i = 0; i < XVECLEN (split, 2); i++)
553    {
554      rtx next = XVECEXP (split, 2, i);
555      if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
556          || (GET_CODE (next) == PARALLEL
557              && GET_CODE (XVECEXP (next, 0, 0)) == SET
558              && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
559          || GET_CODE (next) == RETURN)
560        printf ("  emit_jump_insn (");
561      else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
562               || GET_CODE (next) == CALL
563               || (GET_CODE (next) == PARALLEL
564                   && GET_CODE (XVECEXP (next, 0, 0)) == SET
565                   && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
566               || (GET_CODE (next) == PARALLEL
567                   && GET_CODE (XVECEXP (next, 0, 0)) == CALL))
568        printf ("  emit_call_insn (");
569      else if (GET_CODE (next) == CODE_LABEL)
570        printf ("  emit_label (");
571      else if (GET_CODE (next) == MATCH_OPERAND
572               || GET_CODE (next) == MATCH_OPERATOR
573               || GET_CODE (next) == MATCH_PARALLEL
574               || GET_CODE (next) == MATCH_OP_DUP
575               || GET_CODE (next) == MATCH_DUP
576               || GET_CODE (next) == PARALLEL)
577        printf ("  emit (");
578      else
579        printf ("  emit_insn (");
580      gen_exp (next);
581      printf (");\n");
582      if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
583          && GET_CODE (SET_SRC (next)) == LABEL_REF)
584        printf ("  emit_barrier ();");
585    }
586
587  /* Call `gen_sequence' to make a SEQUENCE out of all the
588     insns emitted within this gen_... function.  */
589
590  printf (" _done:\n");
591  printf ("  _val = gen_sequence ();\n");
592  printf (" _fail:\n");
593  printf ("  end_sequence ();\n");
594  printf ("  return _val;\n}\n\n");
595}
596
597/* Write a function, `add_clobbers', that is given a PARALLEL of sufficient
598   size for the insn and an INSN_CODE, and inserts the required CLOBBERs at
599   the end of the vector.  */
600
601static void
602output_add_clobbers ()
603{
604  struct clobber_pat *clobber;
605  struct clobber_ent *ent;
606  int i;
607
608  printf ("\n\nvoid\nadd_clobbers (pattern, insn_code_number)\n");
609  printf ("     rtx pattern;\n     int insn_code_number;\n");
610  printf ("{\n");
611  printf ("  int i;\n\n");
612  printf ("  switch (insn_code_number)\n");
613  printf ("    {\n");
614
615  for (clobber = clobber_list; clobber; clobber = clobber->next)
616    {
617      for (ent = clobber->insns; ent; ent = ent->next)
618        printf ("    case %d:\n", ent->code_number);
619
620      for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++)
621        {
622          printf ("      XVECEXP (pattern, 0, %d) = ", i);
623          gen_exp (XVECEXP (clobber->pattern, 1, i));
624          printf (";\n");
625        }
626
627      printf ("      break;\n\n");
628    }
629
630  printf ("    default:\n");
631  printf ("      abort ();\n");
632  printf ("    }\n");
633  printf ("}\n");
634}
635
636/* Write a function, init_mov_optab, that is called to set up entries
637   in mov_optab for EXTRA_CC_MODES.  */
638
639static void
640output_init_mov_optab ()
641{
642#ifdef EXTRA_CC_NAMES
643  static char *cc_names[] = { EXTRA_CC_NAMES };
644  char *p;
645  int i;
646
647  printf ("\nvoid\ninit_mov_optab ()\n{\n");
648
649  for (i = 0; i < sizeof cc_names / sizeof cc_names[0]; i++)
650    {
651      printf ("#ifdef HAVE_mov");
652      for (p = cc_names[i]; *p; p++)
653        printf ("%c", *p >= 'A' && *p <= 'Z' ? *p - 'A' + 'a' : *p);
654      printf ("\n");
655      printf ("  if (HAVE_mov");
656      for (p = cc_names[i]; *p; p++)
657        printf ("%c", *p >= 'A' && *p <= 'Z' ? *p - 'A' + 'a' : *p);
658      printf (")\n");
659      printf ("    mov_optab->handlers[(int) %smode].insn_code = CODE_FOR_mov",
660              cc_names[i]);
661      for (p = cc_names[i]; *p; p++)
662        printf ("%c", *p >= 'A' && *p <= 'Z' ? *p - 'A' + 'a' : *p);
663      printf (";\n#endif\n");
664    }
665
666  printf ("}\n");
667#endif
668}
669
670char *
671xmalloc (size)
672     unsigned size;
673{
674  register char *val = (char *) malloc (size);
675
676  if (val == 0)
677    fatal ("virtual memory exhausted");
678
679  return val;
680}
681
682char *
683xrealloc (ptr, size)
684     char *ptr;
685     unsigned size;
686{
687  char *result = (char *) realloc (ptr, size);
688  if (!result)
689    fatal ("virtual memory exhausted");
690  return result;
691}
692
693static void
694fatal (s, a1, a2)
695     char *s;
696{
697  fprintf (stderr, "genemit: ");
698  fprintf (stderr, s, a1, a2);
699  fprintf (stderr, "\n");
700  exit (FATAL_EXIT_CODE);
701}
702
703/* More 'friendly' abort that prints the line and file.
704   config.h can #define abort fancy_abort if you like that sort of thing.  */
705
706void
707fancy_abort ()
708{
709  fatal ("Internal gcc abort.");
710}
711
712int
713main (argc, argv)
714     int argc;
715     char **argv;
716{
717  rtx desc;
718  FILE *infile;
719  register int c;
720
721  obstack_init (rtl_obstack);
722
723  if (argc <= 1)
724    fatal ("No input file name.");
725
726  infile = fopen (argv[1], "r");
727  if (infile == 0)
728    {
729      perror (argv[1]);
730      exit (FATAL_EXIT_CODE);
731    }
732
733  init_rtl ();
734
735  /* Assign sequential codes to all entries in the machine description
736     in parallel with the tables in insn-output.c.  */
737
738  insn_code_number = 0;
739  insn_index_number = 0;
740
741  printf ("/* Generated automatically by the program `genemit'\n\
742from the machine description file `md'.  */\n\n");
743
744  printf ("#include \"config.h\"\n");
745  printf ("#include \"rtl.h\"\n");
746  printf ("#include \"expr.h\"\n");
747  printf ("#include \"real.h\"\n");
748  printf ("#include \"output.h\"\n");
749  printf ("#include \"insn-config.h\"\n\n");
750  printf ("#include \"insn-flags.h\"\n\n");
751  printf ("#include \"insn-codes.h\"\n\n");
752  printf ("extern char *insn_operand_constraint[][MAX_RECOG_OPERANDS];\n\n");
753  printf ("extern rtx recog_operand[];\n");
754  printf ("#define operands emit_operand\n\n");
755  printf ("#define FAIL goto _fail\n\n");
756  printf ("#define DONE goto _done\n\n");
757
758  /* Read the machine description.  */
759
760  while (1)
761    {
762      c = read_skip_spaces (infile);
763      if (c == EOF)
764        break;
765      ungetc (c, infile);
766
767      desc = read_rtx (infile);
768      if (GET_CODE (desc) == DEFINE_INSN)
769        {
770          gen_insn (desc);
771          ++insn_code_number;
772        }
773      if (GET_CODE (desc) == DEFINE_EXPAND)
774        {
775          gen_expand (desc);
776          ++insn_code_number;
777        }
778      if (GET_CODE (desc) == DEFINE_SPLIT)
779        {
780          gen_split (desc);
781          ++insn_code_number;
782        }
783      if (GET_CODE (desc) == DEFINE_PEEPHOLE)
784        {
785          ++insn_code_number;
786        }
787      ++insn_index_number;
788    }
789
790  /* Write out the routine to add CLOBBERs to a pattern.  */
791  output_add_clobbers ();
792
793  /* Write the routine to initialize mov_optab for the EXTRA_CC_MODES.  */
794  output_init_mov_optab ();
795
796  fflush (stdout);
797  exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
798  /* NOTREACHED */
799  return 0;
800}
Note: See TracBrowser for help on using the repository browser.