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