]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/genoutput.c
* c-decl.c (pushdecl): Set DECL_ORIGINAL_TYPE once only.
[thirdparty/gcc.git] / gcc / genoutput.c
CommitLineData
9db4e0ec 1/* Generate code from to output assembler insns as recognized from rtl.
2f013c71 2 Copyright (C) 1987, 88, 92, 94, 95, 1997 Free Software Foundation, Inc.
9db4e0ec
RK
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
a35311b0
RK
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
9db4e0ec
RK
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\f
93#include <stdio.h>
20f92396 94#include "hconfig.h"
9db4e0ec
RK
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 ();
31d04616 111extern rtx read_rtx ();
9db4e0ec
RK
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;
6a270722
RK
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;
9db4e0ec
RK
174\f
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 {
52a1f21f 226 if (d->name && d->name[0] != '*')
9db4e0ec
RK
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
35a3523c 241 for (n = insn_data, next = 1; n; n = n->next, next++)
9db4e0ec
RK
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\f
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];
5a806d65 411static char seen[MAX_MAX_OPERANDS];
9db4e0ec
RK
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)
5a806d65 433 {
de6a431b 434 error ("Too many operands (%d) in definition %d.\n",
5a806d65
RK
435 max_opno + 1, next_index_number);
436 return;
437 }
438 if (seen[opno])
de6a431b 439 error ("Definition %d specified operand number %d more than once.\n",
5a806d65
RK
440 next_index_number, opno);
441 seen[opno] = 1;
9db4e0ec
RK
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)
5a806d65 459 {
de6a431b 460 error ("Too many operands (%d) in definition %d.\n",
5a806d65
RK
461 max_opno + 1, next_index_number);
462 return;
463 }
464 if (seen[opno])
de6a431b 465 error ("Definition %d specified operand number %d more than once.\n",
5a806d65
RK
466 next_index_number, opno);
467 seen[opno] = 1;
9db4e0ec
RK
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)
5a806d65 486 {
de6a431b 487 error ("Too many operands (%d) in definition %d.\n",
5a806d65
RK
488 max_opno + 1, next_index_number);
489 return;
490 }
491 if (seen[opno])
de6a431b 492 error ("Definition %d specified operand number %d more than once.\n",
5a806d65
RK
493 next_index_number, opno);
494 seen[opno] = 1;
9db4e0ec
RK
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:
ed18f94d 506 case MATCH_PAR_DUP:
9db4e0ec
RK
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\f
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')
2f013c71
RK
584 {
585 putchar (*cp);
586 cp++;
587 }
9db4e0ec
RK
588
589 printf ("\",\n");
590 i++;
591 }
592
593 printf (" };\n");
594 printf (" return strings_%d[which_alternative];\n", d->code_number);
595
596 if (i != d->n_alternatives)
597 fatal ("Insn pattern %d has %d alternatives but %d assembler choices",
598 d->index_number, d->n_alternatives, i);
599
600 }
601 else
602 {
603 /* The following is done in a funny way to get around problems in
604 VAX-11 "C" on VMS. It is the equivalent of:
605 printf ("%s\n", &template[1])); */
606 cp = &template[1];
2f013c71
RK
607 while (*cp)
608 {
609 putchar (*cp);
610 cp++;
611 }
9db4e0ec
RK
612 putchar ('\n');
613 }
614
615 printf ("}\n");
616}
617\f
618/* Check insn D for consistency in number of constraint alternatives. */
619
620static void
621validate_insn_alternatives (d)
622 struct data *d;
623{
624 register int n = 0, start;
625 /* Make sure all the operands have the same number of
626 alternatives in their constraints.
627 Let N be that number. */
628 for (start = 0; start < d->n_operands; start++)
629 if (d->op_n_alternatives[start] > 0)
630 {
631 if (n == 0)
632 n = d->op_n_alternatives[start];
633 else if (n != d->op_n_alternatives[start])
634 error ("wrong number of alternatives in operand %d of insn number %d",
635 start, d->index_number);
636 }
637 /* Record the insn's overall number of alternatives. */
638 d->n_alternatives = n;
639}
640\f
641/* Look at a define_insn just read. Assign its code number.
642 Record on insn_data the template and the number of arguments.
643 If the insn has a hairy output action, output a function for now. */
644
645static void
646gen_insn (insn)
647 rtx insn;
648{
649 register struct data *d = (struct data *) xmalloc (sizeof (struct data));
650 register int i;
651
652 d->code_number = next_code_number++;
653 d->index_number = next_index_number;
654 if (XSTR (insn, 0)[0])
655 d->name = XSTR (insn, 0);
656 else
657 d->name = 0;
658
659 /* Build up the list in the same order as the insns are seen
660 in the machine description. */
661 d->next = 0;
662 if (end_of_insn_data)
663 end_of_insn_data->next = d;
664 else
665 insn_data = d;
666
667 end_of_insn_data = d;
668
669 max_opno = -1;
670 num_dups = 0;
671
672 mybzero (constraints, sizeof constraints);
673 mybzero (op_n_alternatives, sizeof op_n_alternatives);
674 mybzero (predicates, sizeof predicates);
675 mybzero (address_p, sizeof address_p);
676 mybzero (modes, sizeof modes);
677 mybzero (strict_low, sizeof strict_low);
5a806d65 678 mybzero (seen, sizeof seen);
9db4e0ec
RK
679
680 for (i = 0; i < XVECLEN (insn, 1); i++)
681 scan_operands (XVECEXP (insn, 1, i), 0, 0);
682
683 d->n_operands = max_opno + 1;
684 d->n_dups = num_dups;
685
686 mybcopy (constraints, d->constraints, sizeof constraints);
687 mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
688 mybcopy (predicates, d->predicates, sizeof predicates);
689 mybcopy (address_p, d->address_p, sizeof address_p);
690 mybcopy (modes, d->modes, sizeof modes);
691 mybcopy (strict_low, d->strict_low, sizeof strict_low);
692
693 validate_insn_alternatives (d);
694 process_template (d, XSTR (insn, 3));
695}
696\f
697/* Look at a define_peephole just read. Assign its code number.
698 Record on insn_data the template and the number of arguments.
699 If the insn has a hairy output action, output it now. */
700
701static void
702gen_peephole (peep)
703 rtx peep;
704{
705 register struct data *d = (struct data *) xmalloc (sizeof (struct data));
706 register int i;
707
708 d->code_number = next_code_number++;
709 d->index_number = next_index_number;
710 d->name = 0;
711
712 /* Build up the list in the same order as the insns are seen
713 in the machine description. */
714 d->next = 0;
715 if (end_of_insn_data)
716 end_of_insn_data->next = d;
717 else
718 insn_data = d;
719
720 end_of_insn_data = d;
721
722 max_opno = -1;
723 mybzero (constraints, sizeof constraints);
724 mybzero (op_n_alternatives, sizeof op_n_alternatives);
5a806d65
RK
725 mybzero (predicates, sizeof predicates);
726 mybzero (address_p, sizeof address_p);
727 mybzero (modes, sizeof modes);
728 mybzero (strict_low, sizeof strict_low);
729 mybzero (seen, sizeof seen);
9db4e0ec
RK
730
731 /* Get the number of operands by scanning all the
732 patterns of the peephole optimizer.
733 But ignore all the rest of the information thus obtained. */
734 for (i = 0; i < XVECLEN (peep, 0); i++)
735 scan_operands (XVECEXP (peep, 0, i), 0, 0);
736
737 d->n_operands = max_opno + 1;
738 d->n_dups = 0;
739
740 mybcopy (constraints, d->constraints, sizeof constraints);
741 mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
742 mybzero (d->predicates, sizeof predicates);
743 mybzero (d->address_p, sizeof address_p);
744 mybzero (d->modes, sizeof modes);
745 mybzero (d->strict_low, sizeof strict_low);
746
747 validate_insn_alternatives (d);
748 process_template (d, XSTR (peep, 2));
749}
750\f
751/* Process a define_expand just read. Assign its code number,
752 only for the purposes of `insn_gen_function'. */
753
754static void
755gen_expand (insn)
756 rtx insn;
757{
758 register struct data *d = (struct data *) xmalloc (sizeof (struct data));
759 register int i;
760
761 d->code_number = next_code_number++;
762 d->index_number = next_index_number;
763 if (XSTR (insn, 0)[0])
764 d->name = XSTR (insn, 0);
765 else
766 d->name = 0;
767
768 /* Build up the list in the same order as the insns are seen
769 in the machine description. */
770 d->next = 0;
771 if (end_of_insn_data)
772 end_of_insn_data->next = d;
773 else
774 insn_data = d;
775
776 end_of_insn_data = d;
777
778 max_opno = -1;
779 num_dups = 0;
780
781 /* Scan the operands to get the specified predicates and modes,
782 since expand_binop needs to know them. */
783
784 mybzero (constraints, sizeof constraints);
785 mybzero (op_n_alternatives, sizeof op_n_alternatives);
786 mybzero (predicates, sizeof predicates);
787 mybzero (address_p, sizeof address_p);
788 mybzero (modes, sizeof modes);
789 mybzero (strict_low, sizeof strict_low);
5a806d65 790 mybzero (seen, sizeof seen);
9db4e0ec
RK
791
792 if (XVEC (insn, 1))
793 for (i = 0; i < XVECLEN (insn, 1); i++)
794 scan_operands (XVECEXP (insn, 1, i), 0, 0);
795
796 d->n_operands = max_opno + 1;
797 d->n_dups = num_dups;
798
799 mybcopy (constraints, d->constraints, sizeof constraints);
800 mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
801 mybcopy (predicates, d->predicates, sizeof predicates);
802 mybcopy (address_p, d->address_p, sizeof address_p);
803 mybcopy (modes, d->modes, sizeof modes);
804 mybcopy (strict_low, d->strict_low, sizeof strict_low);
805
806 d->template = 0;
807 d->outfun = 0;
808 validate_insn_alternatives (d);
809}
810\f
811/* Process a define_split just read. Assign its code number,
812 only for reasons of consistency and to simplify genrecog. */
813
814
815static void
816gen_split (split)
817 rtx split;
818{
819 register struct data *d = (struct data *) xmalloc (sizeof (struct data));
820 register int i;
821
822 d->code_number = next_code_number++;
823 d->index_number = next_index_number;
824 d->name = 0;
825
826 /* Build up the list in the same order as the insns are seen
827 in the machine description. */
828 d->next = 0;
829 if (end_of_insn_data)
830 end_of_insn_data->next = d;
831 else
832 insn_data = d;
833
834 end_of_insn_data = d;
835
836 max_opno = -1;
837 num_dups = 0;
838
839 mybzero (constraints, sizeof constraints);
840 mybzero (op_n_alternatives, sizeof op_n_alternatives);
5a806d65
RK
841 mybzero (predicates, sizeof predicates);
842 mybzero (address_p, sizeof address_p);
843 mybzero (modes, sizeof modes);
844 mybzero (strict_low, sizeof strict_low);
845 mybzero (seen, sizeof seen);
9db4e0ec
RK
846
847 /* Get the number of operands by scanning all the
848 patterns of the split patterns.
849 But ignore all the rest of the information thus obtained. */
850 for (i = 0; i < XVECLEN (split, 0); i++)
851 scan_operands (XVECEXP (split, 0, i), 0, 0);
852
853 d->n_operands = max_opno + 1;
854
855 mybzero (d->constraints, sizeof constraints);
856 mybzero (d->op_n_alternatives, sizeof op_n_alternatives);
857 mybzero (d->predicates, sizeof predicates);
858 mybzero (d->address_p, sizeof address_p);
859 mybzero (d->modes, sizeof modes);
860 mybzero (d->strict_low, sizeof strict_low);
861
862 d->n_dups = 0;
42495ca0 863 d->n_alternatives = 0;
9db4e0ec
RK
864 d->template = 0;
865 d->outfun = 0;
866}
867\f
868char *
869xmalloc (size)
870 unsigned size;
871{
872 register char *val = (char *) malloc (size);
873
874 if (val == 0)
875 fatal ("virtual memory exhausted");
876 return val;
877}
878
879char *
880xrealloc (ptr, size)
881 char *ptr;
882 unsigned size;
883{
884 char *result = (char *) realloc (ptr, size);
885 if (!result)
886 fatal ("virtual memory exhausted");
887 return result;
888}
889
890static void
891mybzero (b, length)
892 register char *b;
893 register unsigned length;
894{
895 while (length-- > 0)
896 *b++ = 0;
897}
898
899static void
900mybcopy (b1, b2, length)
901 register char *b1;
902 register char *b2;
903 register unsigned length;
904{
905 while (length-- > 0)
906 *b2++ = *b1++;
907}
908
909static void
910fatal (s, a1, a2, a3, a4)
911 char *s;
912{
913 fprintf (stderr, "genoutput: ");
914 fprintf (stderr, s, a1, a2, a3, a4);
915 fprintf (stderr, "\n");
916 exit (FATAL_EXIT_CODE);
917}
918
919/* More 'friendly' abort that prints the line and file.
920 config.h can #define abort fancy_abort if you like that sort of thing. */
921
922void
923fancy_abort ()
924{
925 fatal ("Internal gcc abort.");
926}
927
928static void
929error (s, a1, a2)
930 char *s;
931{
932 fprintf (stderr, "genoutput: ");
933 fprintf (stderr, s, a1, a2);
934 fprintf (stderr, "\n");
6a270722
RK
935
936 have_error = 1;
9db4e0ec
RK
937}
938\f
939int
940main (argc, argv)
941 int argc;
942 char **argv;
943{
944 rtx desc;
945 FILE *infile;
9db4e0ec
RK
946 register int c;
947
948 obstack_init (rtl_obstack);
949
950 if (argc <= 1)
951 fatal ("No input file name.");
952
953 infile = fopen (argv[1], "r");
954 if (infile == 0)
955 {
956 perror (argv[1]);
957 exit (FATAL_EXIT_CODE);
958 }
959
960 init_rtl ();
961
962 output_prologue ();
963 next_code_number = 0;
964 next_index_number = 0;
965 have_constraints = 0;
966
967 /* Read the machine description. */
968
969 while (1)
970 {
971 c = read_skip_spaces (infile);
972 if (c == EOF)
973 break;
974 ungetc (c, infile);
975
976 desc = read_rtx (infile);
977 if (GET_CODE (desc) == DEFINE_INSN)
978 gen_insn (desc);
979 if (GET_CODE (desc) == DEFINE_PEEPHOLE)
980 gen_peephole (desc);
981 if (GET_CODE (desc) == DEFINE_EXPAND)
982 gen_expand (desc);
983 if (GET_CODE (desc) == DEFINE_SPLIT)
984 gen_split (desc);
985 next_index_number++;
986 }
987
988 output_epilogue ();
989
990 fflush (stdout);
6a270722
RK
991 exit (ferror (stdout) != 0 || have_error
992 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
993
9db4e0ec
RK
994 /* NOTREACHED */
995 return 0;
996}
997
998static int
999n_occurrences (c, s)
d149d5f5 1000 int c;
9db4e0ec
RK
1001 char *s;
1002{
1003 int n = 0;
1004 while (*s)
1005 n += (*s++ == c);
1006 return n;
1007}