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