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