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