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