|
|
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 ();
110:
111: char *xmalloc ();
112: static void fatal ();
113: void fancy_abort ();
114: static void error ();
115: static void mybcopy ();
116: static void mybzero ();
117: static 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:
123: static int next_code_number;
124:
125: /* This counts all definitions in the md file,
126: for the sake of error messages. */
127:
128: static 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:
133: struct 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:
155: struct data *insn_data;
156:
157: /* Pointer to the last link in the chain, so new elements
158: can be added at the end. */
159:
160: struct 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:
166: int have_constraints;
167:
168: static void
169: output_prologue ()
170: {
171:
172: printf ("/* Generated automatically by the program `genoutput'\n\
173: from 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:
191: static void
192: output_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:
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:
396: static int max_opno;
397: static int num_dups;
398: static char *constraints[MAX_MAX_OPERANDS];
399: static int op_n_alternatives[MAX_MAX_OPERANDS];
400: static char *predicates[MAX_MAX_OPERANDS];
401: static char address_p[MAX_MAX_OPERANDS];
402: static enum machine_mode modes[MAX_MAX_OPERANDS];
403: static char strict_low[MAX_MAX_OPERANDS];
404: static char seen[MAX_MAX_OPERANDS];
405:
406: static void
407: scan_operands (part, this_address_p, this_strict_low)
408: rtx part;
409: int this_address_p;
410: int this_strict_low;
411: {
412: register int i, j;
413: register char *format_ptr;
414: int opno;
415:
416: if (part == 0)
417: return;
418:
419: switch (GET_CODE (part))
420: {
421: case MATCH_OPERAND:
422: opno = XINT (part, 0);
423: if (opno > max_opno)
424: max_opno = opno;
425: if (max_opno >= MAX_MAX_OPERANDS)
426: {
427: error ("Too many operands (%d) in definition %d.\n",
428: max_opno + 1, next_index_number);
429: return;
430: }
431: if (seen[opno])
432: error ("Definition %d specified operand number %d more than once.\n",
433: next_index_number, opno);
434: seen[opno] = 1;
435: modes[opno] = GET_MODE (part);
436: strict_low[opno] = this_strict_low;
437: predicates[opno] = XSTR (part, 1);
438: constraints[opno] = XSTR (part, 2);
439: if (XSTR (part, 2) != 0 && *XSTR (part, 2) != 0)
440: {
441: op_n_alternatives[opno] = n_occurrences (',', XSTR (part, 2)) + 1;
442: have_constraints = 1;
443: }
444: address_p[opno] = this_address_p;
445: return;
446:
447: case MATCH_SCRATCH:
448: opno = XINT (part, 0);
449: if (opno > max_opno)
450: max_opno = opno;
451: if (max_opno >= MAX_MAX_OPERANDS)
452: {
453: error ("Too many operands (%d) in definition %d.\n",
454: max_opno + 1, next_index_number);
455: return;
456: }
457: if (seen[opno])
458: error ("Definition %d specified operand number %d more than once.\n",
459: next_index_number, opno);
460: seen[opno] = 1;
461: modes[opno] = GET_MODE (part);
462: strict_low[opno] = 0;
463: predicates[opno] = "scratch_operand";
464: constraints[opno] = XSTR (part, 1);
465: if (XSTR (part, 1) != 0 && *XSTR (part, 1) != 0)
466: {
467: op_n_alternatives[opno] = n_occurrences (',', XSTR (part, 1)) + 1;
468: have_constraints = 1;
469: }
470: address_p[opno] = 0;
471: return;
472:
473: case MATCH_OPERATOR:
474: case MATCH_PARALLEL:
475: opno = XINT (part, 0);
476: if (opno > max_opno)
477: max_opno = opno;
478: if (max_opno >= MAX_MAX_OPERANDS)
479: {
480: error ("Too many operands (%d) in definition %d.\n",
481: max_opno + 1, next_index_number);
482: return;
483: }
484: if (seen[opno])
485: error ("Definition %d specified operand number %d more than once.\n",
486: next_index_number, opno);
487: seen[opno] = 1;
488: modes[opno] = GET_MODE (part);
489: strict_low[opno] = 0;
490: predicates[opno] = XSTR (part, 1);
491: constraints[opno] = 0;
492: address_p[opno] = 0;
493: for (i = 0; i < XVECLEN (part, 2); i++)
494: scan_operands (XVECEXP (part, 2, i), 0, 0);
495: return;
496:
497: case MATCH_DUP:
498: case MATCH_OP_DUP:
499: ++num_dups;
500: return;
501:
502: case ADDRESS:
503: scan_operands (XEXP (part, 0), 1, 0);
504: return;
505:
506: case STRICT_LOW_PART:
507: scan_operands (XEXP (part, 0), 0, 1);
508: return;
509: }
510:
511: format_ptr = GET_RTX_FORMAT (GET_CODE (part));
512:
513: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
514: switch (*format_ptr++)
515: {
516: case 'e':
517: scan_operands (XEXP (part, i), 0, 0);
518: break;
519: case 'E':
520: if (XVEC (part, i) != NULL)
521: for (j = 0; j < XVECLEN (part, i); j++)
522: scan_operands (XVECEXP (part, i, j), 0, 0);
523: break;
524: }
525: }
526:
527: /* Process an assembler template from a define_insn or a define_peephole.
528: It is either the assembler code template, a list of assembler code
529: templates, or C code to generate the assembler code template. */
530:
531: static void
532: process_template (d, template)
533: struct data *d;
534: char *template;
535: {
536: register char *cp;
537: register int i;
538:
539: /* We need to consider only the instructions whose assembler code template
540: starts with a * or @. These are the ones where C code is run to decide
541: on a template to use. So for all others just return now. */
542:
543: if (template[0] != '*' && template[0] != '@')
544: {
545: d->template = template;
546: d->outfun = 0;
547: return;
548: }
549:
550: d->template = 0;
551: d->outfun = 1;
552:
553: printf ("\nstatic char *\n");
554: printf ("output_%d (operands, insn)\n", d->code_number);
555: printf (" rtx *operands;\n");
556: printf (" rtx insn;\n");
557: printf ("{\n");
558:
559: /* If the assembler code template starts with a @ it is a newline-separated
560: list of assembler code templates, one for each alternative. So produce
561: a routine to select the correct one. */
562:
563: if (template[0] == '@')
564: {
565:
566: printf (" static /*const*/ char *const strings_%d[] = {\n",
567: d->code_number);
568:
569: for (i = 0, cp = &template[1]; *cp; )
570: {
571: while (*cp == '\n' || *cp == ' ' || *cp== '\t')
572: cp++;
573:
574: printf (" \"");
575: while (*cp != '\n' && *cp != '\0')
576: putchar (*cp++);
577:
578: printf ("\",\n");
579: i++;
580: }
581:
582: printf (" };\n");
583: printf (" return strings_%d[which_alternative];\n", d->code_number);
584:
585: if (i != d->n_alternatives)
586: fatal ("Insn pattern %d has %d alternatives but %d assembler choices",
587: d->index_number, d->n_alternatives, i);
588:
589: }
590: else
591: {
592: /* The following is done in a funny way to get around problems in
593: VAX-11 "C" on VMS. It is the equivalent of:
594: printf ("%s\n", &template[1])); */
595: cp = &template[1];
596: while (*cp) putchar (*cp++);
597: putchar ('\n');
598: }
599:
600: printf ("}\n");
601: }
602:
603: /* Check insn D for consistency in number of constraint alternatives. */
604:
605: static void
606: validate_insn_alternatives (d)
607: struct data *d;
608: {
609: register int n = 0, start;
610: /* Make sure all the operands have the same number of
611: alternatives in their constraints.
612: Let N be that number. */
613: for (start = 0; start < d->n_operands; start++)
614: if (d->op_n_alternatives[start] > 0)
615: {
616: if (n == 0)
617: n = d->op_n_alternatives[start];
618: else if (n != d->op_n_alternatives[start])
619: error ("wrong number of alternatives in operand %d of insn number %d",
620: start, d->index_number);
621: }
622: /* Record the insn's overall number of alternatives. */
623: d->n_alternatives = n;
624: }
625:
626: /* Look at a define_insn just read. Assign its code number.
627: Record on insn_data the template and the number of arguments.
628: If the insn has a hairy output action, output a function for now. */
629:
630: static void
631: gen_insn (insn)
632: rtx insn;
633: {
634: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
635: register int i;
636:
637: d->code_number = next_code_number++;
638: d->index_number = next_index_number;
639: if (XSTR (insn, 0)[0])
640: d->name = XSTR (insn, 0);
641: else
642: d->name = 0;
643:
644: /* Build up the list in the same order as the insns are seen
645: in the machine description. */
646: d->next = 0;
647: if (end_of_insn_data)
648: end_of_insn_data->next = d;
649: else
650: insn_data = d;
651:
652: end_of_insn_data = d;
653:
654: max_opno = -1;
655: num_dups = 0;
656:
657: mybzero (constraints, sizeof constraints);
658: mybzero (op_n_alternatives, sizeof op_n_alternatives);
659: mybzero (predicates, sizeof predicates);
660: mybzero (address_p, sizeof address_p);
661: mybzero (modes, sizeof modes);
662: mybzero (strict_low, sizeof strict_low);
663: mybzero (seen, sizeof seen);
664:
665: for (i = 0; i < XVECLEN (insn, 1); i++)
666: scan_operands (XVECEXP (insn, 1, i), 0, 0);
667:
668: d->n_operands = max_opno + 1;
669: d->n_dups = num_dups;
670:
671: mybcopy (constraints, d->constraints, sizeof constraints);
672: mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
673: mybcopy (predicates, d->predicates, sizeof predicates);
674: mybcopy (address_p, d->address_p, sizeof address_p);
675: mybcopy (modes, d->modes, sizeof modes);
676: mybcopy (strict_low, d->strict_low, sizeof strict_low);
677:
678: validate_insn_alternatives (d);
679: process_template (d, XSTR (insn, 3));
680: }
681:
682: /* Look at a define_peephole just read. Assign its code number.
683: Record on insn_data the template and the number of arguments.
684: If the insn has a hairy output action, output it now. */
685:
686: static void
687: gen_peephole (peep)
688: rtx peep;
689: {
690: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
691: register int i;
692:
693: d->code_number = next_code_number++;
694: d->index_number = next_index_number;
695: d->name = 0;
696:
697: /* Build up the list in the same order as the insns are seen
698: in the machine description. */
699: d->next = 0;
700: if (end_of_insn_data)
701: end_of_insn_data->next = d;
702: else
703: insn_data = d;
704:
705: end_of_insn_data = d;
706:
707: max_opno = -1;
708: mybzero (constraints, sizeof constraints);
709: mybzero (op_n_alternatives, sizeof op_n_alternatives);
710: mybzero (predicates, sizeof predicates);
711: mybzero (address_p, sizeof address_p);
712: mybzero (modes, sizeof modes);
713: mybzero (strict_low, sizeof strict_low);
714: mybzero (seen, sizeof seen);
715:
716: /* Get the number of operands by scanning all the
717: patterns of the peephole optimizer.
718: But ignore all the rest of the information thus obtained. */
719: for (i = 0; i < XVECLEN (peep, 0); i++)
720: scan_operands (XVECEXP (peep, 0, i), 0, 0);
721:
722: d->n_operands = max_opno + 1;
723: d->n_dups = 0;
724:
725: mybcopy (constraints, d->constraints, sizeof constraints);
726: mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
727: mybzero (d->predicates, sizeof predicates);
728: mybzero (d->address_p, sizeof address_p);
729: mybzero (d->modes, sizeof modes);
730: mybzero (d->strict_low, sizeof strict_low);
731:
732: validate_insn_alternatives (d);
733: process_template (d, XSTR (peep, 2));
734: }
735:
736: /* Process a define_expand just read. Assign its code number,
737: only for the purposes of `insn_gen_function'. */
738:
739: static void
740: gen_expand (insn)
741: rtx insn;
742: {
743: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
744: register int i;
745:
746: d->code_number = next_code_number++;
747: d->index_number = next_index_number;
748: if (XSTR (insn, 0)[0])
749: d->name = XSTR (insn, 0);
750: else
751: d->name = 0;
752:
753: /* Build up the list in the same order as the insns are seen
754: in the machine description. */
755: d->next = 0;
756: if (end_of_insn_data)
757: end_of_insn_data->next = d;
758: else
759: insn_data = d;
760:
761: end_of_insn_data = d;
762:
763: max_opno = -1;
764: num_dups = 0;
765:
766: /* Scan the operands to get the specified predicates and modes,
767: since expand_binop needs to know them. */
768:
769: mybzero (constraints, sizeof constraints);
770: mybzero (op_n_alternatives, sizeof op_n_alternatives);
771: mybzero (predicates, sizeof predicates);
772: mybzero (address_p, sizeof address_p);
773: mybzero (modes, sizeof modes);
774: mybzero (strict_low, sizeof strict_low);
775: mybzero (seen, sizeof seen);
776:
777: if (XVEC (insn, 1))
778: for (i = 0; i < XVECLEN (insn, 1); i++)
779: scan_operands (XVECEXP (insn, 1, i), 0, 0);
780:
781: d->n_operands = max_opno + 1;
782: d->n_dups = num_dups;
783:
784: mybcopy (constraints, d->constraints, sizeof constraints);
785: mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
786: mybcopy (predicates, d->predicates, sizeof predicates);
787: mybcopy (address_p, d->address_p, sizeof address_p);
788: mybcopy (modes, d->modes, sizeof modes);
789: mybcopy (strict_low, d->strict_low, sizeof strict_low);
790:
791: d->template = 0;
792: d->outfun = 0;
793: validate_insn_alternatives (d);
794: }
795:
796: /* Process a define_split just read. Assign its code number,
797: only for reasons of consistency and to simplify genrecog. */
798:
799:
800: static void
801: gen_split (split)
802: rtx split;
803: {
804: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
805: register int i;
806:
807: d->code_number = next_code_number++;
808: d->index_number = next_index_number;
809: d->name = 0;
810:
811: /* Build up the list in the same order as the insns are seen
812: in the machine description. */
813: d->next = 0;
814: if (end_of_insn_data)
815: end_of_insn_data->next = d;
816: else
817: insn_data = d;
818:
819: end_of_insn_data = d;
820:
821: max_opno = -1;
822: num_dups = 0;
823:
824: mybzero (constraints, sizeof constraints);
825: mybzero (op_n_alternatives, sizeof op_n_alternatives);
826: mybzero (predicates, sizeof predicates);
827: mybzero (address_p, sizeof address_p);
828: mybzero (modes, sizeof modes);
829: mybzero (strict_low, sizeof strict_low);
830: mybzero (seen, sizeof seen);
831:
832: /* Get the number of operands by scanning all the
833: patterns of the split patterns.
834: But ignore all the rest of the information thus obtained. */
835: for (i = 0; i < XVECLEN (split, 0); i++)
836: scan_operands (XVECEXP (split, 0, i), 0, 0);
837:
838: d->n_operands = max_opno + 1;
839:
840: mybzero (d->constraints, sizeof constraints);
841: mybzero (d->op_n_alternatives, sizeof op_n_alternatives);
842: mybzero (d->predicates, sizeof predicates);
843: mybzero (d->address_p, sizeof address_p);
844: mybzero (d->modes, sizeof modes);
845: mybzero (d->strict_low, sizeof strict_low);
846:
847: d->n_dups = 0;
848: d->template = 0;
849: d->outfun = 0;
850: }
851:
852: char *
853: xmalloc (size)
854: unsigned size;
855: {
856: register char *val = (char *) malloc (size);
857:
858: if (val == 0)
859: fatal ("virtual memory exhausted");
860: return val;
861: }
862:
863: char *
864: xrealloc (ptr, size)
865: char *ptr;
866: unsigned size;
867: {
868: char *result = (char *) realloc (ptr, size);
869: if (!result)
870: fatal ("virtual memory exhausted");
871: return result;
872: }
873:
874: static void
875: mybzero (b, length)
876: register char *b;
877: register unsigned length;
878: {
879: while (length-- > 0)
880: *b++ = 0;
881: }
882:
883: static void
884: mybcopy (b1, b2, length)
885: register char *b1;
886: register char *b2;
887: register unsigned length;
888: {
889: while (length-- > 0)
890: *b2++ = *b1++;
891: }
892:
893: static void
894: fatal (s, a1, a2, a3, a4)
895: char *s;
896: {
897: fprintf (stderr, "genoutput: ");
898: fprintf (stderr, s, a1, a2, a3, a4);
899: fprintf (stderr, "\n");
900: exit (FATAL_EXIT_CODE);
901: }
902:
903: /* More 'friendly' abort that prints the line and file.
904: config.h can #define abort fancy_abort if you like that sort of thing. */
905:
906: void
907: fancy_abort ()
908: {
909: fatal ("Internal gcc abort.");
910: }
911:
912: static void
913: error (s, a1, a2)
914: char *s;
915: {
916: fprintf (stderr, "genoutput: ");
917: fprintf (stderr, s, a1, a2);
918: fprintf (stderr, "\n");
919: }
920:
921: int
922: main (argc, argv)
923: int argc;
924: char **argv;
925: {
926: rtx desc;
927: FILE *infile;
928: extern rtx read_rtx ();
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.