OSDN Git Service

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