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

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