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