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

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