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