|
|
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 "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:
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:
500: ++num_dups;
501: return;
502:
503: case ADDRESS:
504: scan_operands (XEXP (part, 0), 1, 0);
505: return;
506:
507: case STRICT_LOW_PART:
508: scan_operands (XEXP (part, 0), 0, 1);
509: return;
510: }
511:
512: format_ptr = GET_RTX_FORMAT (GET_CODE (part));
513:
514: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
515: switch (*format_ptr++)
516: {
517: case 'e':
518: scan_operands (XEXP (part, i), 0, 0);
519: break;
520: case 'E':
521: if (XVEC (part, i) != NULL)
522: for (j = 0; j < XVECLEN (part, i); j++)
523: scan_operands (XVECEXP (part, i, j), 0, 0);
524: break;
525: }
526: }
527:
528: /* Process an assembler template from a define_insn or a define_peephole.
529: It is either the assembler code template, a list of assembler code
530: templates, or C code to generate the assembler code template. */
531:
532: static void
533: process_template (d, template)
534: struct data *d;
535: char *template;
536: {
537: register char *cp;
538: register int i;
539:
540: /* We need to consider only the instructions whose assembler code template
541: starts with a * or @. These are the ones where C code is run to decide
542: on a template to use. So for all others just return now. */
543:
544: if (template[0] != '*' && template[0] != '@')
545: {
546: d->template = template;
547: d->outfun = 0;
548: return;
549: }
550:
551: d->template = 0;
552: d->outfun = 1;
553:
554: printf ("\nstatic char *\n");
555: printf ("output_%d (operands, insn)\n", d->code_number);
556: printf (" rtx *operands;\n");
557: printf (" rtx insn;\n");
558: printf ("{\n");
559:
560: /* If the assembler code template starts with a @ it is a newline-separated
561: list of assembler code templates, one for each alternative. So produce
562: a routine to select the correct one. */
563:
564: if (template[0] == '@')
565: {
566:
567: printf (" static /*const*/ char *const strings_%d[] = {\n",
568: d->code_number);
569:
570: for (i = 0, cp = &template[1]; *cp; )
571: {
572: while (*cp == '\n' || *cp == ' ' || *cp== '\t')
573: cp++;
574:
575: printf (" \"");
576: while (*cp != '\n' && *cp != '\0')
577: putchar (*cp++);
578:
579: printf ("\",\n");
580: i++;
581: }
582:
583: printf (" };\n");
584: printf (" return strings_%d[which_alternative];\n", d->code_number);
585:
586: if (i != d->n_alternatives)
587: fatal ("Insn pattern %d has %d alternatives but %d assembler choices",
588: d->index_number, d->n_alternatives, i);
589:
590: }
591: else
592: {
593: /* The following is done in a funny way to get around problems in
594: VAX-11 "C" on VMS. It is the equivalent of:
595: printf ("%s\n", &template[1])); */
596: cp = &template[1];
597: while (*cp) putchar (*cp++);
598: putchar ('\n');
599: }
600:
601: printf ("}\n");
602: }
603:
604: /* Check insn D for consistency in number of constraint alternatives. */
605:
606: static void
607: validate_insn_alternatives (d)
608: struct data *d;
609: {
610: register int n = 0, start;
611: /* Make sure all the operands have the same number of
612: alternatives in their constraints.
613: Let N be that number. */
614: for (start = 0; start < d->n_operands; start++)
615: if (d->op_n_alternatives[start] > 0)
616: {
617: if (n == 0)
618: n = d->op_n_alternatives[start];
619: else if (n != d->op_n_alternatives[start])
620: error ("wrong number of alternatives in operand %d of insn number %d",
621: start, d->index_number);
622: }
623: /* Record the insn's overall number of alternatives. */
624: d->n_alternatives = n;
625: }
626:
627: /* Look at a define_insn just read. Assign its code number.
628: Record on insn_data the template and the number of arguments.
629: If the insn has a hairy output action, output a function for now. */
630:
631: static void
632: gen_insn (insn)
633: rtx insn;
634: {
635: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
636: register int i;
637:
638: d->code_number = next_code_number++;
639: d->index_number = next_index_number;
640: if (XSTR (insn, 0)[0])
641: d->name = XSTR (insn, 0);
642: else
643: d->name = 0;
644:
645: /* Build up the list in the same order as the insns are seen
646: in the machine description. */
647: d->next = 0;
648: if (end_of_insn_data)
649: end_of_insn_data->next = d;
650: else
651: insn_data = d;
652:
653: end_of_insn_data = d;
654:
655: max_opno = -1;
656: num_dups = 0;
657:
658: mybzero (constraints, sizeof constraints);
659: mybzero (op_n_alternatives, sizeof op_n_alternatives);
660: mybzero (predicates, sizeof predicates);
661: mybzero (address_p, sizeof address_p);
662: mybzero (modes, sizeof modes);
663: mybzero (strict_low, sizeof strict_low);
664: mybzero (seen, sizeof seen);
665:
666: for (i = 0; i < XVECLEN (insn, 1); i++)
667: scan_operands (XVECEXP (insn, 1, i), 0, 0);
668:
669: d->n_operands = max_opno + 1;
670: d->n_dups = num_dups;
671:
672: mybcopy (constraints, d->constraints, sizeof constraints);
673: mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
674: mybcopy (predicates, d->predicates, sizeof predicates);
675: mybcopy (address_p, d->address_p, sizeof address_p);
676: mybcopy (modes, d->modes, sizeof modes);
677: mybcopy (strict_low, d->strict_low, sizeof strict_low);
678:
679: validate_insn_alternatives (d);
680: process_template (d, XSTR (insn, 3));
681: }
682:
683: /* Look at a define_peephole just read. Assign its code number.
684: Record on insn_data the template and the number of arguments.
685: If the insn has a hairy output action, output it now. */
686:
687: static void
688: gen_peephole (peep)
689: rtx peep;
690: {
691: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
692: register int i;
693:
694: d->code_number = next_code_number++;
695: d->index_number = next_index_number;
696: d->name = 0;
697:
698: /* Build up the list in the same order as the insns are seen
699: in the machine description. */
700: d->next = 0;
701: if (end_of_insn_data)
702: end_of_insn_data->next = d;
703: else
704: insn_data = d;
705:
706: end_of_insn_data = d;
707:
708: max_opno = -1;
709: mybzero (constraints, sizeof constraints);
710: mybzero (op_n_alternatives, sizeof op_n_alternatives);
711: mybzero (predicates, sizeof predicates);
712: mybzero (address_p, sizeof address_p);
713: mybzero (modes, sizeof modes);
714: mybzero (strict_low, sizeof strict_low);
715: mybzero (seen, sizeof seen);
716:
717: /* Get the number of operands by scanning all the
718: patterns of the peephole optimizer.
719: But ignore all the rest of the information thus obtained. */
720: for (i = 0; i < XVECLEN (peep, 0); i++)
721: scan_operands (XVECEXP (peep, 0, i), 0, 0);
722:
723: d->n_operands = max_opno + 1;
724: d->n_dups = 0;
725:
726: mybcopy (constraints, d->constraints, sizeof constraints);
727: mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
728: mybzero (d->predicates, sizeof predicates);
729: mybzero (d->address_p, sizeof address_p);
730: mybzero (d->modes, sizeof modes);
731: mybzero (d->strict_low, sizeof strict_low);
732:
733: validate_insn_alternatives (d);
734: process_template (d, XSTR (peep, 2));
735: }
736:
737: /* Process a define_expand just read. Assign its code number,
738: only for the purposes of `insn_gen_function'. */
739:
740: static void
741: gen_expand (insn)
742: rtx insn;
743: {
744: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
745: register int i;
746:
747: d->code_number = next_code_number++;
748: d->index_number = next_index_number;
749: if (XSTR (insn, 0)[0])
750: d->name = XSTR (insn, 0);
751: else
752: d->name = 0;
753:
754: /* Build up the list in the same order as the insns are seen
755: in the machine description. */
756: d->next = 0;
757: if (end_of_insn_data)
758: end_of_insn_data->next = d;
759: else
760: insn_data = d;
761:
762: end_of_insn_data = d;
763:
764: max_opno = -1;
765: num_dups = 0;
766:
767: /* Scan the operands to get the specified predicates and modes,
768: since expand_binop needs to know them. */
769:
770: mybzero (constraints, sizeof constraints);
771: mybzero (op_n_alternatives, sizeof op_n_alternatives);
772: mybzero (predicates, sizeof predicates);
773: mybzero (address_p, sizeof address_p);
774: mybzero (modes, sizeof modes);
775: mybzero (strict_low, sizeof strict_low);
776: mybzero (seen, sizeof seen);
777:
778: if (XVEC (insn, 1))
779: for (i = 0; i < XVECLEN (insn, 1); i++)
780: scan_operands (XVECEXP (insn, 1, i), 0, 0);
781:
782: d->n_operands = max_opno + 1;
783: d->n_dups = num_dups;
784:
785: mybcopy (constraints, d->constraints, sizeof constraints);
786: mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
787: mybcopy (predicates, d->predicates, sizeof predicates);
788: mybcopy (address_p, d->address_p, sizeof address_p);
789: mybcopy (modes, d->modes, sizeof modes);
790: mybcopy (strict_low, d->strict_low, sizeof strict_low);
791:
792: d->template = 0;
793: d->outfun = 0;
794: validate_insn_alternatives (d);
795: }
796:
797: /* Process a define_split just read. Assign its code number,
798: only for reasons of consistency and to simplify genrecog. */
799:
800:
801: static void
802: gen_split (split)
803: rtx split;
804: {
805: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
806: register int i;
807:
808: d->code_number = next_code_number++;
809: d->index_number = next_index_number;
810: d->name = 0;
811:
812: /* Build up the list in the same order as the insns are seen
813: in the machine description. */
814: d->next = 0;
815: if (end_of_insn_data)
816: end_of_insn_data->next = d;
817: else
818: insn_data = d;
819:
820: end_of_insn_data = d;
821:
822: max_opno = -1;
823: num_dups = 0;
824:
825: mybzero (constraints, sizeof constraints);
826: mybzero (op_n_alternatives, sizeof op_n_alternatives);
827: mybzero (predicates, sizeof predicates);
828: mybzero (address_p, sizeof address_p);
829: mybzero (modes, sizeof modes);
830: mybzero (strict_low, sizeof strict_low);
831: mybzero (seen, sizeof seen);
832:
833: /* Get the number of operands by scanning all the
834: patterns of the split patterns.
835: But ignore all the rest of the information thus obtained. */
836: for (i = 0; i < XVECLEN (split, 0); i++)
837: scan_operands (XVECEXP (split, 0, i), 0, 0);
838:
839: d->n_operands = max_opno + 1;
840:
841: mybzero (d->constraints, sizeof constraints);
842: mybzero (d->op_n_alternatives, sizeof op_n_alternatives);
843: mybzero (d->predicates, sizeof predicates);
844: mybzero (d->address_p, sizeof address_p);
845: mybzero (d->modes, sizeof modes);
846: mybzero (d->strict_low, sizeof strict_low);
847:
848: d->n_dups = 0;
849: d->template = 0;
850: d->outfun = 0;
851: }
852:
853: char *
854: xmalloc (size)
855: unsigned size;
856: {
857: register char *val = (char *) malloc (size);
858:
859: if (val == 0)
860: fatal ("virtual memory exhausted");
861: return val;
862: }
863:
864: char *
865: xrealloc (ptr, size)
866: char *ptr;
867: unsigned size;
868: {
869: char *result = (char *) realloc (ptr, size);
870: if (!result)
871: fatal ("virtual memory exhausted");
872: return result;
873: }
874:
875: static void
876: mybzero (b, length)
877: register char *b;
878: register unsigned length;
879: {
880: while (length-- > 0)
881: *b++ = 0;
882: }
883:
884: static void
885: mybcopy (b1, b2, length)
886: register char *b1;
887: register char *b2;
888: register unsigned length;
889: {
890: while (length-- > 0)
891: *b2++ = *b1++;
892: }
893:
894: static void
895: fatal (s, a1, a2, a3, a4)
896: char *s;
897: {
898: fprintf (stderr, "genoutput: ");
899: fprintf (stderr, s, a1, a2, a3, a4);
900: fprintf (stderr, "\n");
901: exit (FATAL_EXIT_CODE);
902: }
903:
904: /* More 'friendly' abort that prints the line and file.
905: config.h can #define abort fancy_abort if you like that sort of thing. */
906:
907: void
908: fancy_abort ()
909: {
910: fatal ("Internal gcc abort.");
911: }
912:
913: static void
914: error (s, a1, a2)
915: char *s;
916: {
917: fprintf (stderr, "genoutput: ");
918: fprintf (stderr, s, a1, a2);
919: fprintf (stderr, "\n");
920: }
921:
922: int
923: main (argc, argv)
924: int argc;
925: char **argv;
926: {
927: rtx desc;
928: FILE *infile;
929: register int c;
930:
931: obstack_init (rtl_obstack);
932:
933: if (argc <= 1)
934: fatal ("No input file name.");
935:
936: infile = fopen (argv[1], "r");
937: if (infile == 0)
938: {
939: perror (argv[1]);
940: exit (FATAL_EXIT_CODE);
941: }
942:
943: init_rtl ();
944:
945: output_prologue ();
946: next_code_number = 0;
947: next_index_number = 0;
948: have_constraints = 0;
949:
950: /* Read the machine description. */
951:
952: while (1)
953: {
954: c = read_skip_spaces (infile);
955: if (c == EOF)
956: break;
957: ungetc (c, infile);
958:
959: desc = read_rtx (infile);
960: if (GET_CODE (desc) == DEFINE_INSN)
961: gen_insn (desc);
962: if (GET_CODE (desc) == DEFINE_PEEPHOLE)
963: gen_peephole (desc);
964: if (GET_CODE (desc) == DEFINE_EXPAND)
965: gen_expand (desc);
966: if (GET_CODE (desc) == DEFINE_SPLIT)
967: gen_split (desc);
968: next_index_number++;
969: }
970:
971: output_epilogue ();
972:
973: fflush (stdout);
974: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
975: /* NOTREACHED */
976: return 0;
977: }
978:
979: static int
980: n_occurrences (c, s)
981: char c;
982: char *s;
983: {
984: int n = 0;
985: while (*s)
986: n += (*s++ == c);
987: return n;
988: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.