OSDN Git Service

*** empty log message ***
[pf3gnuchains/gcc-fork.git] / gcc / genoutput.c
1 /* Generate code from to output assembler insns as recognized from rtl.
2    Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20
21 /* This program reads the machine description for the compiler target machine
22    and produces a file containing these things:
23
24    1. An array of strings `insn_template' which is indexed by insn code number
25    and contains the template for output of that insn,
26
27    2. An array of functions `insn_outfun' which, indexed by the insn code
28    number, gives the function that returns a template to use for output of
29    that insn.  This is used only in the cases where the template is not
30    constant.  These cases are specified by a * or @ at the beginning of the
31    template string in the machine description.  They are identified for the
32    sake of other parts of the compiler by a zero element in `insn_template'.
33   
34    3. An array of functions `insn_gen_function' which, indexed
35    by insn code number, gives the function to generate a body
36    for that pattern, given operands as arguments.
37
38    4. An array of strings `insn_name' which, indexed by insn code number,
39    gives the name for that pattern.  Nameless patterns are given a name.
40
41    5. An array of ints `insn_n_operands' which is indexed by insn code number
42    and contains the number of distinct operands in the pattern for that insn,
43
44    6. An array of ints `insn_n_dups' which is indexed by insn code number
45    and contains the number of match_dup's that appear in the insn's pattern.
46    This says how many elements of `recog_dup_loc' are significant
47    after an insn has been recognized.
48
49    7. An array of arrays of operand constraint strings,
50    `insn_operand_constraint',
51    indexed first by insn code number and second by operand number,
52    containing the constraint for that operand.
53
54    This array is generated only if register constraints appear in 
55    match_operand rtx's.
56
57    8. An array of arrays of chars which indicate which operands of
58    which insn patterns appear within ADDRESS rtx's.  This array is
59    called `insn_operand_address_p' and is generated only if there
60    are *no* register constraints in the match_operand rtx's.
61
62    9. An array of arrays of machine modes, `insn_operand_mode',
63    indexed first by insn code number and second by operand number,
64    containing the machine mode that that operand is supposed to have.
65    Also `insn_operand_strict_low', which is nonzero for operands
66    contained in a STRICT_LOW_PART.
67
68    10. An array of arrays of int-valued functions, `insn_operand_predicate',
69    indexed first by insn code number and second by operand number,
70    containing the match_operand predicate for this operand.
71
72    11. An array of ints, `insn_n_alternatives', that gives the number
73    of alternatives in the constraints of each pattern.
74
75 The code number of an insn is simply its position in the machine description;
76 code numbers are assigned sequentially to entries in the description,
77 starting with code number 0.
78
79 Thus, the following entry in the machine description
80
81     (define_insn "clrdf"
82       [(set (match_operand:DF 0 "general_operand" "")
83             (const_int 0))]
84       ""
85       "clrd %0")
86
87 assuming it is the 25th entry present, would cause
88 insn_template[24] to be "clrd %0", and insn_n_operands[24] to be 1.
89 It would not make an case in output_insn_hairy because the template
90 given in the entry is a constant (it does not start with `*').  */
91 \f
92 #include <stdio.h>
93 #include "config.h"
94 #include "rtl.h"
95 #include "obstack.h"
96
97 /* No instruction can have more operands than this.
98    Sorry for this arbitrary limit, but what machine will
99    have an instruction with this many operands?  */
100
101 #define MAX_MAX_OPERANDS 40
102
103 static struct obstack obstack;
104 struct obstack *rtl_obstack = &obstack;
105
106 #define obstack_chunk_alloc xmalloc
107 #define obstack_chunk_free free
108
109 extern void free ();
110 extern rtx read_rtx ();
111
112 char *xmalloc ();
113 static void fatal ();
114 void fancy_abort ();
115 static void error ();
116 static void mybcopy ();
117 static void mybzero ();
118 static int n_occurrences ();
119
120 /* insns in the machine description are assigned sequential code numbers
121    that are used by insn-recog.c (produced by genrecog) to communicate
122    to insn-output.c (produced by this program).  */
123
124 static int next_code_number;
125
126 /* This counts all definitions in the md file,
127    for the sake of error messages.  */
128
129 static int next_index_number;
130
131 /* Record in this chain all information that we will output,
132    associated with the code number of the insn.  */
133
134 struct data
135 {
136   int code_number;
137   int index_number;
138   char *name;
139   char *template;               /* string such as "movl %1,%0" */
140   int n_operands;               /* Number of operands this insn recognizes */
141   int n_dups;                   /* Number times match_dup appears in pattern */
142   int n_alternatives;           /* Number of alternatives in each constraint */
143   struct data *next;
144   char *constraints[MAX_MAX_OPERANDS];
145   /* Number of alternatives in constraints of operand N.  */
146   int op_n_alternatives[MAX_MAX_OPERANDS];
147   char *predicates[MAX_MAX_OPERANDS];
148   char address_p[MAX_MAX_OPERANDS];
149   enum machine_mode modes[MAX_MAX_OPERANDS];
150   char strict_low[MAX_MAX_OPERANDS];
151   char outfun;                  /* Nonzero means this has an output function */
152 };
153
154 /* This variable points to the first link in the chain.  */
155
156 struct data *insn_data;
157
158 /* Pointer to the last link in the chain, so new elements
159    can be added at the end.  */
160
161 struct data *end_of_insn_data;
162
163 /* Nonzero if any match_operand has a constraint string;
164    implies that REGISTER_CONSTRAINTS will be defined
165    for this machine description.  */
166
167 int have_constraints;
168 \f
169 static void
170 output_prologue ()
171 {
172
173   printf ("/* Generated automatically by the program `genoutput'\n\
174 from the machine description file `md'.  */\n\n");
175
176   printf ("#include \"config.h\"\n");
177   printf ("#include \"rtl.h\"\n");
178   printf ("#include \"regs.h\"\n");
179   printf ("#include \"hard-reg-set.h\"\n");
180   printf ("#include \"real.h\"\n");
181   printf ("#include \"insn-config.h\"\n\n");
182   printf ("#include \"conditions.h\"\n");
183   printf ("#include \"insn-flags.h\"\n");
184   printf ("#include \"insn-attr.h\"\n\n");
185   printf ("#include \"insn-codes.h\"\n\n");
186   printf ("#include \"recog.h\"\n\n");
187
188   printf ("#include <stdio.h>\n");
189   printf ("#include \"output.h\"\n");
190 }
191
192 static void
193 output_epilogue ()
194 {
195   register struct data *d;
196
197   printf ("\nchar * const insn_template[] =\n  {\n");
198   for (d = insn_data; d; d = d->next)
199     {
200       if (d->template)
201         printf ("    \"%s\",\n", d->template);
202       else
203         printf ("    0,\n");
204     }
205   printf ("  };\n");
206
207   printf ("\nchar *(*const insn_outfun[])() =\n  {\n");
208   for (d = insn_data; d; d = d->next)
209     {
210       if (d->outfun)
211         printf ("    output_%d,\n", d->code_number);
212       else
213         printf ("    0,\n");
214     }
215   printf ("  };\n");
216
217   printf ("\nrtx (*const insn_gen_function[]) () =\n  {\n");
218   for (d = insn_data; d; d = d->next)
219     {
220       if (d->name)
221         printf ("    gen_%s,\n", d->name);
222       else
223         printf ("    0,\n");
224     }
225   printf ("  };\n");
226
227   printf ("\nchar *insn_name[] =\n  {\n");
228   {
229     int offset = 0;
230     int next;
231     char * last_name = 0;
232     char * next_name;
233     register struct data *n;
234
235     for (n = insn_data, next = 0; n; n = n->next, next++)
236       if (n->name)
237         {
238           next_name = n->name;
239           break;
240         }
241
242     for (d = insn_data; d; d = d->next)
243       {
244         if (d->name)
245           {
246             printf ("    \"%s\",\n", d->name);
247             offset = 0;
248             last_name = d->name;
249             next_name = 0;
250             for (n = d->next, next = 1; n; n = n->next, next++)
251               if (n->name)
252                 {
253                   next_name = n->name;
254                   break;
255                 }
256           }
257         else
258           {
259             offset++;
260             if (next_name && (last_name == 0 || offset > next / 2))
261               printf ("    \"%s-%d\",\n", next_name, next - offset);
262             else
263               printf ("    \"%s+%d\",\n", last_name, offset);
264           }
265       }
266   }
267   printf ("  };\n");
268   printf ("char **insn_name_ptr = insn_name;\n");
269
270   printf ("\nconst int insn_n_operands[] =\n  {\n");
271   for (d = insn_data; d; d = d->next)
272     printf ("    %d,\n", d->n_operands);
273   printf ("  };\n");
274
275   printf ("\nconst int insn_n_dups[] =\n  {\n");
276   for (d = insn_data; d; d = d->next)
277     printf ("    %d,\n", d->n_dups);
278   printf ("  };\n");
279
280   if (have_constraints)
281     {
282       printf ("\nchar *const insn_operand_constraint[][MAX_RECOG_OPERANDS] =\n  {\n");
283       for (d = insn_data; d; d = d->next)
284         {
285           register int i;
286           printf ("    {");
287           for (i = 0; i < d->n_operands; i++)
288             {
289               if (d->constraints[i] == 0)
290                 printf (" \"\",");
291               else
292                 printf (" \"%s\",", d->constraints[i]);
293             }
294           if (d->n_operands == 0)
295             printf (" 0");
296           printf (" },\n");
297         }
298       printf ("  };\n");
299     }
300   else
301     {
302       printf ("\nconst char insn_operand_address_p[][MAX_RECOG_OPERANDS] =\n  {\n");
303       for (d = insn_data; d; d = d->next)
304         {
305           register int i;
306           printf ("    {");
307           for (i = 0; i < d->n_operands; i++)
308             printf (" %d,", d->address_p[i]);
309           if (d->n_operands == 0)
310             printf (" 0");
311           printf (" },\n");
312         }
313       printf ("  };\n");
314     }
315
316   printf ("\nconst enum machine_mode insn_operand_mode[][MAX_RECOG_OPERANDS] =\n  {\n");
317   for (d = insn_data; d; d = d->next)
318     {
319       register int i;
320       printf ("    {");
321       for (i = 0; i < d->n_operands; i++)
322         printf (" %smode,", GET_MODE_NAME (d->modes[i]));
323       if (d->n_operands == 0)
324         printf (" VOIDmode");
325       printf (" },\n");
326     }
327   printf ("  };\n");
328
329   printf ("\nconst char insn_operand_strict_low[][MAX_RECOG_OPERANDS] =\n  {\n");
330   for (d = insn_data; d; d = d->next)
331     {
332       register int i;
333       printf ("    {");
334       for (i = 0; i < d->n_operands; i++)
335         printf (" %d,", d->strict_low[i]);
336       if (d->n_operands == 0)
337         printf (" 0");
338       printf (" },\n");
339     }
340   printf ("  };\n");
341
342   {
343     /* We need to define all predicates used.  Keep a list of those we
344        have defined so far.  There normally aren't very many predicates used,
345        so a linked list should be fast enough.  */
346     struct predicate { char *name; struct predicate *next; } *predicates = 0;
347     struct predicate *p;
348     int i;
349
350     printf ("\n");
351     for (d = insn_data; d; d = d->next)
352       for (i = 0; i < d->n_operands; i++)
353         if (d->predicates[i] && d->predicates[i][0])
354           {
355             for (p = predicates; p; p = p->next)
356               if (! strcmp (p->name, d->predicates[i]))
357                 break;
358
359             if (p == 0)
360               {
361                 printf ("extern int %s ();\n", d->predicates[i]);
362                 p = (struct predicate *) alloca (sizeof (struct predicate));
363                 p->name = d->predicates[i];
364                 p->next = predicates;
365                 predicates = p;
366               }
367           }
368     
369     printf ("\nint (*const insn_operand_predicate[][MAX_RECOG_OPERANDS])() =\n  {\n");
370     for (d = insn_data; d; d = d->next)
371       {
372         printf ("    {");
373         for (i = 0; i < d->n_operands; i++)
374           printf (" %s,", ((d->predicates[i] && d->predicates[i][0])
375                            ? d->predicates[i] : "0"));
376         if (d->n_operands == 0)
377           printf (" 0");
378         printf (" },\n");
379       }
380     printf ("  };\n");
381   }
382
383   printf ("\nconst int insn_n_alternatives[] =\n  {\n");
384   for (d = insn_data; d; d = d->next)
385     printf ("    %d,\n", d->n_alternatives);
386   printf("  };\n");
387 }
388 \f
389 /* scan_operands (X) stores in max_opno the largest operand
390    number present in X, if that is larger than the previous
391    value of max_opno.  It stores all the constraints in `constraints'
392    and all the machine modes in `modes'.
393
394    THIS_ADDRESS_P is nonzero if the containing rtx was an ADDRESS.
395    THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART.  */
396
397 static int max_opno;
398 static int num_dups;
399 static char *constraints[MAX_MAX_OPERANDS];
400 static int op_n_alternatives[MAX_MAX_OPERANDS];
401 static char *predicates[MAX_MAX_OPERANDS];
402 static char address_p[MAX_MAX_OPERANDS];
403 static enum machine_mode modes[MAX_MAX_OPERANDS];
404 static char strict_low[MAX_MAX_OPERANDS];
405 static char seen[MAX_MAX_OPERANDS];
406
407 static void
408 scan_operands (part, this_address_p, this_strict_low)
409      rtx part;
410      int this_address_p;
411      int this_strict_low;
412 {
413   register int i, j;
414   register char *format_ptr;
415   int opno;
416
417   if (part == 0)
418     return;
419
420   switch (GET_CODE (part))
421     {
422     case MATCH_OPERAND:
423       opno = XINT (part, 0);
424       if (opno > max_opno)
425         max_opno = opno;
426       if (max_opno >= MAX_MAX_OPERANDS)
427         {
428           error ("Too many operands (%d) in definition %d.\n",
429                  max_opno + 1, next_index_number);
430           return;
431         }
432       if (seen[opno])
433         error ("Definition %d specified operand number %d more than once.\n",
434                next_index_number, opno);
435       seen[opno] = 1;
436       modes[opno] = GET_MODE (part);
437       strict_low[opno] = this_strict_low;
438       predicates[opno] = XSTR (part, 1);
439       constraints[opno] = XSTR (part, 2);
440       if (XSTR (part, 2) != 0 && *XSTR (part, 2) != 0)
441         {
442           op_n_alternatives[opno] = n_occurrences (',', XSTR (part, 2)) + 1;
443           have_constraints = 1;
444         }
445       address_p[opno] = this_address_p;
446       return;
447
448     case MATCH_SCRATCH:
449       opno = XINT (part, 0);
450       if (opno > max_opno)
451         max_opno = opno;
452       if (max_opno >= MAX_MAX_OPERANDS)
453         {
454           error ("Too many operands (%d) in definition %d.\n",
455                  max_opno + 1, next_index_number);
456           return;
457         }
458       if (seen[opno])
459         error ("Definition %d specified operand number %d more than once.\n",
460                next_index_number, opno);
461       seen[opno] = 1;
462       modes[opno] = GET_MODE (part);
463       strict_low[opno] = 0;
464       predicates[opno] = "scratch_operand";
465       constraints[opno] = XSTR (part, 1);
466       if (XSTR (part, 1) != 0 && *XSTR (part, 1) != 0)
467         {
468           op_n_alternatives[opno] = n_occurrences (',', XSTR (part, 1)) + 1;
469           have_constraints = 1;
470         }
471       address_p[opno] = 0;
472       return;
473
474     case MATCH_OPERATOR:
475     case MATCH_PARALLEL:
476       opno = XINT (part, 0);
477       if (opno > max_opno)
478         max_opno = opno;
479       if (max_opno >= MAX_MAX_OPERANDS)
480         {
481           error ("Too many operands (%d) in definition %d.\n",
482                  max_opno + 1, next_index_number);
483           return;
484         }
485       if (seen[opno])
486         error ("Definition %d specified operand number %d more than once.\n",
487                next_index_number, opno);
488       seen[opno] = 1;
489       modes[opno] = GET_MODE (part);
490       strict_low[opno] = 0;
491       predicates[opno] = XSTR (part, 1);
492       constraints[opno] = 0;
493       address_p[opno] = 0;
494       for (i = 0; i < XVECLEN (part, 2); i++)
495         scan_operands (XVECEXP (part, 2, i), 0, 0);
496       return;
497
498     case MATCH_DUP:
499     case MATCH_OP_DUP:
500       ++num_dups;
501       return;
502
503     case ADDRESS:
504       scan_operands (XEXP (part, 0), 1, 0);
505       return;
506
507     case STRICT_LOW_PART:
508       scan_operands (XEXP (part, 0), 0, 1);
509       return;
510     }
511
512   format_ptr = GET_RTX_FORMAT (GET_CODE (part));
513
514   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
515     switch (*format_ptr++)
516       {
517       case 'e':
518         scan_operands (XEXP (part, i), 0, 0);
519         break;
520       case 'E':
521         if (XVEC (part, i) != NULL)
522           for (j = 0; j < XVECLEN (part, i); j++)
523             scan_operands (XVECEXP (part, i, j), 0, 0);
524         break;
525       }
526 }
527 \f
528 /* Process an assembler template from a define_insn or a define_peephole.
529    It is either the assembler code template, a list of assembler code
530    templates, or C code to generate the assembler code template.  */
531
532 static void
533 process_template (d, template)
534     struct data *d;
535     char *template;
536 {
537   register char *cp;
538   register int i;
539
540   /* We need to consider only the instructions whose assembler code template
541      starts with a * or @.  These are the ones where C code is run to decide
542      on a template to use.  So for all others just return now.  */
543
544   if (template[0] != '*' && template[0] != '@')
545     {
546       d->template = template;
547       d->outfun = 0;
548       return;
549     }
550
551   d->template = 0;
552   d->outfun = 1;
553
554   printf ("\nstatic char *\n");
555   printf ("output_%d (operands, insn)\n", d->code_number);
556   printf ("     rtx *operands;\n");
557   printf ("     rtx insn;\n");
558   printf ("{\n");
559
560   /* If the assembler code template starts with a @ it is a newline-separated
561      list of assembler code templates, one for each alternative.  So produce
562      a routine to select the correct one.  */
563
564   if (template[0] == '@')
565     {
566
567       printf ("  static /*const*/ char *const strings_%d[] = {\n",
568               d->code_number);
569
570       for (i = 0, cp = &template[1]; *cp; )
571         {
572           while (*cp == '\n' || *cp == ' ' || *cp== '\t')
573             cp++;
574
575           printf ("    \"");
576           while (*cp != '\n' && *cp != '\0')
577             putchar (*cp++);
578
579           printf ("\",\n");
580           i++;
581         }
582
583       printf ("  };\n");
584       printf ("  return strings_%d[which_alternative];\n", d->code_number);
585
586       if (i != d->n_alternatives)
587         fatal ("Insn pattern %d has %d alternatives but %d assembler choices",
588                d->index_number, d->n_alternatives, i);
589
590     }
591   else
592     {
593        /* The following is done in a funny way to get around problems in
594           VAX-11 "C" on VMS.  It is the equivalent of:
595                 printf ("%s\n", &template[1])); */
596       cp = &template[1];
597       while (*cp) putchar (*cp++);
598       putchar ('\n');
599     }
600
601   printf ("}\n");
602 }
603 \f
604 /* Check insn D for consistency in number of constraint alternatives.  */
605
606 static void
607 validate_insn_alternatives (d)
608      struct data *d;
609 {
610   register int n = 0, start;
611   /* Make sure all the operands have the same number of
612      alternatives in their constraints.
613      Let N be that number.  */
614   for (start = 0; start < d->n_operands; start++)
615     if (d->op_n_alternatives[start] > 0)
616       {
617         if (n == 0)
618           n = d->op_n_alternatives[start];
619         else if (n != d->op_n_alternatives[start])
620           error ("wrong number of alternatives in operand %d of insn number %d",
621                  start, d->index_number);
622       }
623   /* Record the insn's overall number of alternatives.  */
624   d->n_alternatives = n;
625 }
626 \f
627 /* Look at a define_insn just read.  Assign its code number.
628    Record on insn_data the template and the number of arguments.
629    If the insn has a hairy output action, output a function for now.  */
630
631 static void
632 gen_insn (insn)
633      rtx insn;
634 {
635   register struct data *d = (struct data *) xmalloc (sizeof (struct data));
636   register int i;
637
638   d->code_number = next_code_number++;
639   d->index_number = next_index_number;
640   if (XSTR (insn, 0)[0])
641     d->name = XSTR (insn, 0);
642   else
643     d->name = 0;
644
645   /* Build up the list in the same order as the insns are seen
646      in the machine description.  */
647   d->next = 0;
648   if (end_of_insn_data)
649     end_of_insn_data->next = d;
650   else
651     insn_data = d;
652
653   end_of_insn_data = d;
654
655   max_opno = -1;
656   num_dups = 0;
657
658   mybzero (constraints, sizeof constraints);
659   mybzero (op_n_alternatives, sizeof op_n_alternatives);
660   mybzero (predicates, sizeof predicates);
661   mybzero (address_p, sizeof address_p);
662   mybzero (modes, sizeof modes);
663   mybzero (strict_low, sizeof strict_low);
664   mybzero (seen, sizeof seen);
665
666   for (i = 0; i < XVECLEN (insn, 1); i++)
667     scan_operands (XVECEXP (insn, 1, i), 0, 0);
668
669   d->n_operands = max_opno + 1;
670   d->n_dups = num_dups;
671
672   mybcopy (constraints, d->constraints, sizeof constraints);
673   mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
674   mybcopy (predicates, d->predicates, sizeof predicates);
675   mybcopy (address_p, d->address_p, sizeof address_p);
676   mybcopy (modes, d->modes, sizeof modes);
677   mybcopy (strict_low, d->strict_low, sizeof strict_low);
678
679   validate_insn_alternatives (d);
680   process_template (d, XSTR (insn, 3));
681 }
682 \f
683 /* Look at a define_peephole just read.  Assign its code number.
684    Record on insn_data the template and the number of arguments.
685    If the insn has a hairy output action, output it now.  */
686
687 static void
688 gen_peephole (peep)
689      rtx peep;
690 {
691   register struct data *d = (struct data *) xmalloc (sizeof (struct data));
692   register int i;
693
694   d->code_number = next_code_number++;
695   d->index_number = next_index_number;
696   d->name = 0;
697
698   /* Build up the list in the same order as the insns are seen
699      in the machine description.  */
700   d->next = 0;
701   if (end_of_insn_data)
702     end_of_insn_data->next = d;
703   else
704     insn_data = d;
705
706   end_of_insn_data = d;
707
708   max_opno = -1;
709   mybzero (constraints, sizeof constraints);
710   mybzero (op_n_alternatives, sizeof op_n_alternatives);
711   mybzero (predicates, sizeof predicates);
712   mybzero (address_p, sizeof address_p);
713   mybzero (modes, sizeof modes);
714   mybzero (strict_low, sizeof strict_low);
715   mybzero (seen, sizeof seen);
716
717   /* Get the number of operands by scanning all the
718      patterns of the peephole optimizer.
719      But ignore all the rest of the information thus obtained.  */
720   for (i = 0; i < XVECLEN (peep, 0); i++)
721     scan_operands (XVECEXP (peep, 0, i), 0, 0);
722
723   d->n_operands = max_opno + 1;
724   d->n_dups = 0;
725
726   mybcopy (constraints, d->constraints, sizeof constraints);
727   mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
728   mybzero (d->predicates, sizeof predicates);
729   mybzero (d->address_p, sizeof address_p);
730   mybzero (d->modes, sizeof modes);
731   mybzero (d->strict_low, sizeof strict_low);
732
733   validate_insn_alternatives (d);
734   process_template (d, XSTR (peep, 2));
735 }
736 \f
737 /* Process a define_expand just read.  Assign its code number,
738    only for the purposes of `insn_gen_function'.  */
739
740 static void
741 gen_expand (insn)
742      rtx insn;
743 {
744   register struct data *d = (struct data *) xmalloc (sizeof (struct data));
745   register int i;
746
747   d->code_number = next_code_number++;
748   d->index_number = next_index_number;
749   if (XSTR (insn, 0)[0])
750     d->name = XSTR (insn, 0);
751   else
752     d->name = 0;
753
754   /* Build up the list in the same order as the insns are seen
755      in the machine description.  */
756   d->next = 0;
757   if (end_of_insn_data)
758     end_of_insn_data->next = d;
759   else
760     insn_data = d;
761
762   end_of_insn_data = d;
763
764   max_opno = -1;
765   num_dups = 0;
766
767   /* Scan the operands to get the specified predicates and modes,
768      since expand_binop needs to know them.  */
769
770   mybzero (constraints, sizeof constraints);
771   mybzero (op_n_alternatives, sizeof op_n_alternatives);
772   mybzero (predicates, sizeof predicates);
773   mybzero (address_p, sizeof address_p);
774   mybzero (modes, sizeof modes);
775   mybzero (strict_low, sizeof strict_low);
776   mybzero (seen, sizeof seen);
777
778   if (XVEC (insn, 1))
779     for (i = 0; i < XVECLEN (insn, 1); i++)
780       scan_operands (XVECEXP (insn, 1, i), 0, 0);
781
782   d->n_operands = max_opno + 1;
783   d->n_dups = num_dups;
784
785   mybcopy (constraints, d->constraints, sizeof constraints);
786   mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
787   mybcopy (predicates, d->predicates, sizeof predicates);
788   mybcopy (address_p, d->address_p, sizeof address_p);
789   mybcopy (modes, d->modes, sizeof modes);
790   mybcopy (strict_low, d->strict_low, sizeof strict_low);
791
792   d->template = 0;
793   d->outfun = 0;
794   validate_insn_alternatives (d);
795 }
796 \f
797 /* Process a define_split just read.  Assign its code number,
798    only for reasons of consistency and to simplify genrecog.  */
799
800
801 static void
802 gen_split (split)
803      rtx split;
804 {
805   register struct data *d = (struct data *) xmalloc (sizeof (struct data));
806   register int i;
807
808   d->code_number = next_code_number++;
809   d->index_number = next_index_number;
810   d->name = 0;
811
812   /* Build up the list in the same order as the insns are seen
813      in the machine description.  */
814   d->next = 0;
815   if (end_of_insn_data)
816     end_of_insn_data->next = d;
817   else
818     insn_data = d;
819
820   end_of_insn_data = d;
821
822   max_opno = -1;
823   num_dups = 0;
824
825   mybzero (constraints, sizeof constraints);
826   mybzero (op_n_alternatives, sizeof op_n_alternatives);
827   mybzero (predicates, sizeof predicates);
828   mybzero (address_p, sizeof address_p);
829   mybzero (modes, sizeof modes);
830   mybzero (strict_low, sizeof strict_low);
831   mybzero (seen, sizeof seen);
832
833   /* Get the number of operands by scanning all the
834      patterns of the split patterns.
835      But ignore all the rest of the information thus obtained.  */
836   for (i = 0; i < XVECLEN (split, 0); i++)
837     scan_operands (XVECEXP (split, 0, i), 0, 0);
838
839   d->n_operands = max_opno + 1;
840
841   mybzero (d->constraints, sizeof constraints);
842   mybzero (d->op_n_alternatives, sizeof op_n_alternatives);
843   mybzero (d->predicates, sizeof predicates);
844   mybzero (d->address_p, sizeof address_p);
845   mybzero (d->modes, sizeof modes);
846   mybzero (d->strict_low, sizeof strict_low);
847
848   d->n_dups = 0;
849   d->template = 0;
850   d->outfun = 0;
851   d->n_alternatives = 0;
852 }
853 \f
854 char *
855 xmalloc (size)
856      unsigned size;
857 {
858   register char *val = (char *) malloc (size);
859
860   if (val == 0)
861     fatal ("virtual memory exhausted");
862   return val;
863 }
864
865 char *
866 xrealloc (ptr, size)
867      char *ptr;
868      unsigned size;
869 {
870   char *result = (char *) realloc (ptr, size);
871   if (!result)
872     fatal ("virtual memory exhausted");
873   return result;
874 }
875
876 static void
877 mybzero (b, length)
878      register char *b;
879      register unsigned length;
880 {
881   while (length-- > 0)
882     *b++ = 0;
883 }
884
885 static void
886 mybcopy (b1, b2, length)
887      register char *b1;
888      register char *b2;
889      register unsigned length;
890 {
891   while (length-- > 0)
892     *b2++ = *b1++;
893 }
894
895 static void
896 fatal (s, a1, a2, a3, a4)
897      char *s;
898 {
899   fprintf (stderr, "genoutput: ");
900   fprintf (stderr, s, a1, a2, a3, a4);
901   fprintf (stderr, "\n");
902   exit (FATAL_EXIT_CODE);
903 }
904
905 /* More 'friendly' abort that prints the line and file.
906    config.h can #define abort fancy_abort if you like that sort of thing.  */
907
908 void
909 fancy_abort ()
910 {
911   fatal ("Internal gcc abort.");
912 }
913
914 static void
915 error (s, a1, a2)
916      char *s;
917 {
918   fprintf (stderr, "genoutput: ");
919   fprintf (stderr, s, a1, a2);
920   fprintf (stderr, "\n");
921 }
922 \f
923 int
924 main (argc, argv)
925      int argc;
926      char **argv;
927 {
928   rtx desc;
929   FILE *infile;
930   register int c;
931
932   obstack_init (rtl_obstack);
933
934   if (argc <= 1)
935     fatal ("No input file name.");
936
937   infile = fopen (argv[1], "r");
938   if (infile == 0)
939     {
940       perror (argv[1]);
941       exit (FATAL_EXIT_CODE);
942     }
943
944   init_rtl ();
945
946   output_prologue ();
947   next_code_number = 0;
948   next_index_number = 0;
949   have_constraints = 0;
950
951   /* Read the machine description.  */
952
953   while (1)
954     {
955       c = read_skip_spaces (infile);
956       if (c == EOF)
957         break;
958       ungetc (c, infile);
959
960       desc = read_rtx (infile);
961       if (GET_CODE (desc) == DEFINE_INSN)
962         gen_insn (desc);
963       if (GET_CODE (desc) == DEFINE_PEEPHOLE)
964         gen_peephole (desc);
965       if (GET_CODE (desc) == DEFINE_EXPAND)
966         gen_expand (desc);
967       if (GET_CODE (desc) == DEFINE_SPLIT)
968         gen_split (desc);
969       next_index_number++;
970     }
971
972   output_epilogue ();
973
974   fflush (stdout);
975   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
976   /* NOTREACHED */
977   return 0;
978 }
979
980 static int
981 n_occurrences (c, s)
982      char c;
983      char *s;
984 {
985   int n = 0;
986   while (*s)
987     n += (*s++ == c);
988   return n;
989 }