|
|
1.1 root 1: /* Generate code from to output assembler insns as recognized from rtl.
2: Copyright (C) 1987 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: /* This program reads the machine description for the compiler target machine
23: and produces a file containing three things:
24:
25: 1, An array of strings `insn_template' which is indexed by insn code number
26: and contains the template for output of that insn,
27:
28: 2. An array of ints `insn_n_operands' which is indexed by insn code number
29: and contains the number of distinct operands in the pattern for that insn,
30:
31: 3. An array of ints `insn_n_dups' which is indexed by insn code number
32: and contains the number of match_dup's that appear in the insn's pattern.
33: This says how many elements of `recog_dup_loc' are significant
34: after an insn has been recognized.
35:
1.1.1.2 root 36: 4. An array of arrays of operand constraint strings,
1.1 root 37: `insn_operand_constraint',
38: indexed first by insn code number and second by operand number,
39: containing the constraint for that operand.
1.1.1.2 root 40:
1.1 root 41: This array is generated only if register constraints appear in
42: match_operand rtx's.
43:
1.1.1.2 root 44: 5. An array of arrays of chars which indicate which operands of
1.1 root 45: which insn patterns appear within ADDRESS rtx's. This array is
46: called `insn_operand_address_p' and is generated only if there
47: are *no* register constraints in the match_operand rtx's.
48:
1.1.1.2 root 49: 6. An array of arrays of machine modes, `insn_operand_mode',
50: indexed first by insn code number and second by operand number,
51: containing the machine mode that that operand is supposed to have.
52: Also `insn_operand_strict_low', which is nonzero for operands
53: contained in a STRICT_LOW_PART.
54:
55: 7. An array of arrays of int-valued functions, `insn_operand_predicate',
56: indexed first by insn code number and second by operand number,
57: containing the match_operand predicate for this operand.
58:
59: 8. An array of functions `insn_gen_function' which, indexed
1.1 root 60: by insn code number, gives the function to generate a body
61: for that patter, given operands as arguments.
62:
1.1.1.2 root 63: 9. A function `output_insn_hairy' which is called with two arguments
1.1 root 64: (an insn code number and a vector of operand value rtx's)
65: and returns a template to use for output of that insn.
66: This is used only in the cases where the template is not constant.
67: These cases are specified by a * at the beginning of the template string
68: in the machine description. They are identified for the sake of
69: other parts of the compiler by a zero element in `insn_template'.
1.1.1.4 root 70:
71: 10. An array of structures, `insn_machine_info', that gives machine-specific
72: information about the insn.
1.1 root 73:
1.1.1.5 ! root 74: 11. An array of ints, `insn_n_alternatives', that gives the number
! 75: of alternatives in the constraints of each pattern.
! 76:
1.1 root 77: The code number of an insn is simply its position in the machine description;
78: code numbers are assigned sequentially to entries in the description,
79: starting with code number 0.
80:
81: Thus, the following entry in the machine description
82:
83: (define_insn "clrdf"
84: [(set (match_operand:DF 0 "general_operand" "")
85: (const_int 0))]
86: ""
87: "clrd %0")
88:
89: assuming it is the 25th entry present, would cause
1.1.1.2 root 90: insn_template[24] to be "clrd %0", and insn_n_operands[24] to be 1.
1.1 root 91: It would not make an case in output_insn_hairy because the template
92: given in the entry is a constant (it does not start with `*'). */
93:
94: #include <stdio.h>
1.1.1.2 root 95: #include "config.h"
1.1 root 96: #include "rtl.h"
1.1.1.2 root 97: #include "obstack.h"
1.1 root 98:
99: /* No instruction can have more operands than this.
100: Sorry for this arbitrary limit, but what machine will
101: have an instruction with this many operands? */
102:
103: #define MAX_MAX_OPERANDS 40
104:
105: struct obstack obstack;
1.1.1.2 root 106: struct obstack *rtl_obstack = &obstack;
1.1 root 107:
108: #define obstack_chunk_alloc xmalloc
109: #define obstack_chunk_free free
110: extern int xmalloc ();
111: extern void free ();
112:
113: void fatal ();
1.1.1.2 root 114: void mybcopy ();
115: void mybzero ();
1.1 root 116:
117: /* insns in the machine description are assigned sequential code numbers
118: that are used by insn-recog.c (produced by genrecog) to communicate
119: to insn-output.c (produced by this program). */
120:
121: int next_code_number;
122:
123: /* Record in this chain all information that we will output,
124: associated with the code number of the insn. */
125:
126: struct data
127: {
128: int code_number;
129: char *name;
130: char *template; /* string such as "movl %1,%0" */
131: int n_operands; /* Number of operands this insn recognizes */
132: int n_dups; /* Number times match_dup appears in pattern */
1.1.1.5 ! root 133: int n_alternatives; /* Number of alternatives in each constraint */
1.1 root 134: struct data *next;
135: char *constraints[MAX_MAX_OPERANDS];
1.1.1.5 ! root 136: /* Number of alternatives in constraints of operand N. */
! 137: int op_n_alternatives[MAX_MAX_OPERANDS];
1.1.1.2 root 138: char *predicates[MAX_MAX_OPERANDS];
1.1 root 139: char address_p[MAX_MAX_OPERANDS];
140: enum machine_mode modes[MAX_MAX_OPERANDS];
1.1.1.2 root 141: char strict_low[MAX_MAX_OPERANDS];
142: char outfun; /* Nonzero means this has an output function */
1.1.1.4 root 143: char *machine_info; /* machine-specific info string. */
1.1 root 144: };
145:
146: /* This variable points to the first link in the chain. */
147:
148: struct data *insn_data;
149:
150: /* Pointer to the last link in the chain, so new elements
151: can be added at the end. */
152:
153: struct data *end_of_insn_data;
154:
155: /* Nonzero if any match_operand has a constraint string;
156: implies that REGISTER_CONSTRAINTS will be defined
157: for this machine description. */
158:
159: int have_constraints;
160:
161: void
162: output_prologue ()
163: {
164:
165: printf ("/* Generated automatically by the program `genoutput'\n\
166: from the machine description file `md'. */\n\n");
167:
168: printf ("#include \"config.h\"\n");
169: printf ("#include \"rtl.h\"\n");
170: printf ("#include \"regs.h\"\n");
171: printf ("#include \"conditions.h\"\n");
172: printf ("#include \"insn-flags.h\"\n");
173: printf ("#include \"insn-config.h\"\n\n");
174:
1.1.1.4 root 175: printf ("#ifndef __STDC__\n");
176: printf ("#define const\n");
177: printf ("#endif\n\n");
178:
179: printf ("#include \"output.h\"\n");
1.1 root 180: printf ("#include \"aux-output.c\"\n\n");
1.1.1.4 root 181:
182: /* Make sure there is at least a dummy definition of INSN_MACHINE_INFO. */
183: printf ("#ifndef INSN_MACHINE_INFO\n");
184: printf ("#define INSN_MACHINE_INFO struct dummy1 {int i;}\n");
185: printf ("#endif\n\n");
1.1 root 186: }
187:
188: void
189: output_epilogue ()
190: {
191: register struct data *d;
192:
1.1.1.4 root 193: printf ("\nchar * const insn_template[] =\n {\n");
1.1 root 194: for (d = insn_data; d; d = d->next)
195: {
196: if (d->template)
197: printf (" \"%s\",\n", d->template);
198: else
199: printf (" 0,\n");
200: }
201: printf (" };\n");
202:
1.1.1.4 root 203: printf ("\nchar *(*const insn_outfun[])() =\n {\n");
1.1.1.2 root 204: for (d = insn_data; d; d = d->next)
205: {
206: if (d->outfun)
1.1.1.3 root 207: printf (" output_%d,\n", d->code_number);
1.1.1.2 root 208: else
209: printf (" 0,\n");
210: }
211: printf (" };\n");
212:
1.1.1.4 root 213: printf ("\nrtx (*const insn_gen_function[]) () =\n {\n");
1.1 root 214: for (d = insn_data; d; d = d->next)
215: {
216: if (d->name)
217: printf (" gen_%s,\n", d->name);
218: else
219: printf (" 0,\n");
220: }
221: printf (" };\n");
222:
1.1.1.4 root 223: printf ("\nconst int insn_n_operands[] =\n {\n");
1.1 root 224: for (d = insn_data; d; d = d->next)
225: {
226: printf (" %d,\n", d->n_operands);
227: }
228: printf (" };\n");
229:
1.1.1.4 root 230: printf ("\nconst int insn_n_dups[] =\n {\n");
1.1 root 231: for (d = insn_data; d; d = d->next)
232: {
233: printf (" %d,\n", d->n_dups);
234: }
235: printf (" };\n");
236:
237: if (have_constraints)
238: {
1.1.1.4 root 239: printf ("\nchar *const insn_operand_constraint[][MAX_RECOG_OPERANDS] =\n {\n");
1.1 root 240: for (d = insn_data; d; d = d->next)
241: {
1.1.1.5 ! root 242: register int i, n = 0, start;
1.1 root 243: printf (" {");
1.1.1.5 ! root 244: /* Make sure all the operands have the same number of
! 245: alternatives in their constraints.
! 246: Let N be that number. */
! 247: for (start = 0; start < d->n_operands; start++)
! 248: if (d->op_n_alternatives[start] > 0)
! 249: {
! 250: if (n == 0)
! 251: n = d->op_n_alternatives[start];
! 252: else if (n != d->op_n_alternatives[start])
! 253: fatal ("wrong number of alternatives in operand %d of insn number %d",
! 254: start, d->code_number);
! 255: break;
! 256: }
! 257: /* Record the insn's overall number of alternatives. */
! 258: d->n_alternatives = n;
! 259:
1.1 root 260: for (i = 0; i < d->n_operands; i++)
1.1.1.2 root 261: {
262: if (d->constraints[i] == 0)
263: printf (" \"\",");
264: else
265: printf (" \"%s\",", d->constraints[i]);
266: }
1.1 root 267: if (d->n_operands == 0)
268: printf (" 0");
269: printf (" },\n");
270: }
271: printf (" };\n");
272: }
273: else
274: {
1.1.1.4 root 275: printf ("\nconst char insn_operand_address_p[][MAX_RECOG_OPERANDS] =\n {\n");
1.1 root 276: for (d = insn_data; d; d = d->next)
277: {
278: register int i;
279: printf (" {");
280: for (i = 0; i < d->n_operands; i++)
281: printf (" %d,", d->address_p[i]);
282: if (d->n_operands == 0)
283: printf (" 0");
284: printf (" },\n");
285: }
286: printf (" };\n");
287: }
288:
1.1.1.4 root 289: printf ("\nconst enum machine_mode insn_operand_mode[][MAX_RECOG_OPERANDS] =\n {\n");
1.1 root 290: for (d = insn_data; d; d = d->next)
291: {
292: register int i;
293: printf (" {");
294: for (i = 0; i < d->n_operands; i++)
295: printf (" %smode,", GET_MODE_NAME (d->modes[i]));
296: if (d->n_operands == 0)
297: printf (" VOIDmode");
298: printf (" },\n");
299: }
300: printf (" };\n");
1.1.1.2 root 301:
1.1.1.4 root 302: printf ("\nconst char insn_operand_strict_low[][MAX_RECOG_OPERANDS] =\n {\n");
1.1.1.2 root 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->strict_low[i]);
309: if (d->n_operands == 0)
310: printf (" 0");
311: printf (" },\n");
312: }
313: printf (" };\n");
314:
1.1.1.4 root 315: printf ("\nint (*const insn_operand_predicate[][MAX_RECOG_OPERANDS])() =\n {\n");
1.1.1.2 root 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 (" %s,", ((d->predicates[i] && d->predicates[i][0])
322: ? d->predicates[i] : "0"));
323: if (d->n_operands == 0)
324: printf (" 0");
325: printf (" },\n");
326: }
327: printf (" };\n");
1.1.1.4 root 328:
329: printf ("\nconst INSN_MACHINE_INFO insn_machine_info[] =\n {\n");
330: for (d = insn_data; d; d = d->next)
331: {
332: if (d->machine_info)
333: printf (" {%s},\n", d->machine_info);
334: else
335: printf(" {0},\n");
336: }
337: printf(" };\n");
1.1.1.5 ! root 338:
! 339: printf ("\nconst int insn_n_alternatives[] =\n {\n");
! 340: for (d = insn_data; d; d = d->next)
! 341: {
! 342: if (d->n_alternatives)
! 343: printf (" %d,\n", d->n_alternatives);
! 344: else
! 345: printf(" 0,\n");
! 346: }
! 347: printf(" };\n");
1.1 root 348: }
349:
350: /* scan_operands (X) stores in max_opno the largest operand
351: number present in X, if that is larger than the previous
352: value of max_opno. It stores all the constraints in `constraints'
1.1.1.2 root 353: and all the machine modes in `modes'.
354:
355: THIS_ADDRESS_P is nonzero if the containing rtx was an ADDRESS.
356: THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART. */
1.1 root 357:
358: int max_opno;
359: int num_dups;
360: char *constraints[MAX_MAX_OPERANDS];
1.1.1.5 ! root 361: int op_n_alternatives[MAX_MAX_OPERANDS];
1.1.1.2 root 362: char *predicates[MAX_MAX_OPERANDS];
1.1 root 363: char address_p[MAX_MAX_OPERANDS];
364: enum machine_mode modes[MAX_MAX_OPERANDS];
1.1.1.2 root 365: char strict_low[MAX_MAX_OPERANDS];
1.1 root 366:
367: void
1.1.1.2 root 368: scan_operands (part, this_address_p, this_strict_low)
1.1 root 369: rtx part;
370: int this_address_p;
1.1.1.2 root 371: int this_strict_low;
1.1 root 372: {
373: register int i, j;
1.1.1.2 root 374: register RTX_CODE code;
1.1 root 375: register char *format_ptr;
376:
1.1.1.2 root 377: if (part == 0)
378: return;
379:
380: code = GET_CODE (part);
381:
1.1 root 382: if (code == MATCH_OPERAND)
383: {
1.1.1.2 root 384: int opno = XINT (part, 0);
385: if (opno > max_opno)
386: max_opno = opno;
387: if (max_opno >= MAX_MAX_OPERANDS)
1.1 root 388: fatal ("Too many operands (%d) in one instruction pattern.\n",
389: max_opno + 1);
1.1.1.2 root 390: modes[opno] = GET_MODE (part);
391: strict_low[opno] = this_strict_low;
392: predicates[opno] = XSTR (part, 1);
393: constraints[opno] = XSTR (part, 2);
1.1 root 394: if (XSTR (part, 2) != 0 && *XSTR (part, 2) != 0)
1.1.1.5 ! root 395: {
! 396: op_n_alternatives[opno] = n_occurrences (',', XSTR (part, 2)) + 1;
! 397: have_constraints = 1;
! 398: }
1.1.1.2 root 399: address_p[opno] = this_address_p;
1.1 root 400: return;
401: }
402:
1.1.1.5 ! root 403: if (code == MATCH_OPERATOR)
! 404: {
! 405: int opno = XINT (part, 0);
! 406: if (opno > max_opno)
! 407: max_opno = opno;
! 408: if (max_opno >= MAX_MAX_OPERANDS)
! 409: fatal ("Too many operands (%d) in one instruction pattern.\n",
! 410: max_opno + 1);
! 411: modes[opno] = GET_MODE (part);
! 412: strict_low[opno] = 0;
! 413: predicates[opno] = XSTR (part, 1);
! 414: constraints[opno] = 0;
! 415: address_p[opno] = 0;
! 416: for (i = 0; i < XVECLEN (part, 2); i++)
! 417: scan_operands (XVECEXP (part, 2, i), 0, 0);
! 418: return;
! 419: }
! 420:
1.1 root 421: if (code == MATCH_DUP)
422: {
423: ++num_dups;
424: return;
425: }
426:
427: if (code == ADDRESS)
428: {
1.1.1.2 root 429: scan_operands (XEXP (part, 0), 1, 0);
430: return;
431: }
432:
433: if (code == STRICT_LOW_PART)
434: {
435: scan_operands (XEXP (part, 0), 0, 1);
1.1 root 436: return;
437: }
438:
439: format_ptr = GET_RTX_FORMAT (GET_CODE (part));
440:
441: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
442: switch (*format_ptr++)
443: {
444: case 'e':
1.1.1.2 root 445: scan_operands (XEXP (part, i), 0, 0);
1.1 root 446: break;
447: case 'E':
448: if (XVEC (part, i) != NULL)
449: for (j = 0; j < XVECLEN (part, i); j++)
1.1.1.2 root 450: scan_operands (XVECEXP (part, i, j), 0, 0);
1.1 root 451: break;
452: }
453: }
454:
1.1.1.2 root 455: /* Look at a define_insn just read. Assign its code number.
1.1 root 456: Record on insn_data the template and the number of arguments.
1.1.1.2 root 457: If the insn has a hairy output action, output a function for now. */
1.1 root 458:
459: void
460: gen_insn (insn)
461: rtx insn;
462: {
463: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
464: register int i;
465:
466: d->code_number = next_code_number++;
467: if (XSTR (insn, 0)[0])
468: d->name = XSTR (insn, 0);
469: else
470: d->name = 0;
471:
472: /* Build up the list in the same order as the insns are seen
473: in the machine description. */
474: d->next = 0;
475: if (end_of_insn_data)
476: end_of_insn_data->next = d;
477: else
478: insn_data = d;
479:
480: end_of_insn_data = d;
481:
482: max_opno = -1;
483: num_dups = 0;
484:
1.1.1.2 root 485: mybzero (constraints, sizeof constraints);
1.1.1.5 ! root 486: mybzero (op_n_alternatives, sizeof op_n_alternatives);
1.1.1.2 root 487: mybzero (predicates, sizeof predicates);
488: mybzero (address_p, sizeof address_p);
489: mybzero (modes, sizeof modes);
490: mybzero (strict_low, sizeof strict_low);
1.1 root 491: for (i = 0; i < XVECLEN (insn, 1); i++)
1.1.1.2 root 492: scan_operands (XVECEXP (insn, 1, i), 0, 0);
1.1 root 493: d->n_operands = max_opno + 1;
494: d->n_dups = num_dups;
1.1.1.2 root 495: mybcopy (constraints, d->constraints, sizeof constraints);
1.1.1.5 ! root 496: mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
1.1.1.2 root 497: mybcopy (predicates, d->predicates, sizeof predicates);
498: mybcopy (address_p, d->address_p, sizeof address_p);
499: mybcopy (modes, d->modes, sizeof modes);
500: mybcopy (strict_low, d->strict_low, sizeof strict_low);
1.1.1.4 root 501: d->machine_info = XSTR (insn, 4);
1.1 root 502:
503: /* We need to consider only the instructions whose assembler code template
504: starts with a *. These are the ones where the template is really
505: C code to run to decide on a template to use.
506: So for all others just return now. */
507:
508: if (XSTR (insn, 3)[0] != '*')
509: {
510: d->template = XSTR (insn, 3);
1.1.1.2 root 511: d->outfun = 0;
1.1 root 512: return;
513: }
514:
515: d->template = 0;
1.1.1.2 root 516: d->outfun = 1;
517:
518: printf ("\nchar *\n");
519: printf ("output_%d (operands, insn)\n", d->code_number);
520: printf (" rtx *operands;\n");
521: printf (" rtx insn;\n");
522: printf ("{\n");
523: /* The following is done in a funny way to get around problems in
524: VAX-11 "C" on VMS. It is the equivalent of:
525: printf ("%s\n", &(XSTR (insn, 3)[1])); */
526: {
527: register char *cp = &(XSTR (insn, 3)[1]);
528: while (*cp) putchar (*cp++);
529: putchar ('\n');
530: }
531: printf ("}\n");
1.1 root 532: }
533:
1.1.1.2 root 534: /* Look at a define_peephole just read. Assign its code number.
535: Record on insn_data the template and the number of arguments.
536: If the insn has a hairy output action, output it now. */
537:
538: void
539: gen_peephole (peep)
540: rtx peep;
541: {
542: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
543: register int i;
544:
545: d->code_number = next_code_number++;
546: d->name = 0;
547:
548: /* Build up the list in the same order as the insns are seen
549: in the machine description. */
550: d->next = 0;
551: if (end_of_insn_data)
552: end_of_insn_data->next = d;
553: else
554: insn_data = d;
555:
556: end_of_insn_data = d;
557:
558: max_opno = -1;
559: mybzero (constraints, sizeof constraints);
1.1.1.5 ! root 560: mybzero (op_n_alternatives, sizeof op_n_alternatives);
1.1.1.2 root 561:
562: /* Get the number of operands by scanning all the
563: patterns of the peephole optimizer.
564: But ignore all the rest of the information thus obtained. */
565: for (i = 0; i < XVECLEN (peep, 0); i++)
566: scan_operands (XVECEXP (peep, 0, i), 0, 0);
567:
568: d->n_operands = max_opno + 1;
569: d->n_dups = 0;
570: mybcopy (constraints, d->constraints, sizeof constraints);
1.1.1.5 ! root 571: mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
1.1.1.2 root 572: mybzero (d->predicates, sizeof predicates);
573: mybzero (d->address_p, sizeof address_p);
574: mybzero (d->modes, sizeof modes);
575: mybzero (d->strict_low, sizeof strict_low);
1.1.1.4 root 576: d->machine_info = XSTR (peep, 3);
1.1.1.2 root 577:
578: /* We need to consider only the instructions whose assembler code template
579: starts with a *. These are the ones where the template is really
580: C code to run to decide on a template to use.
581: So for all others just return now. */
582:
583: if (XSTR (peep, 2)[0] != '*')
584: {
585: d->template = XSTR (peep, 2);
586: d->outfun = 0;
587: return;
588: }
589:
590: d->template = 0;
591: d->outfun = 1;
592:
593: printf ("\nchar *\n");
594: printf ("output_%d (operands, insn)\n", d->code_number);
595: printf (" rtx *operands;\n");
596: printf (" rtx insn;\n");
597: printf ("{\n");
598: printf ("%s\n", &(XSTR (peep, 2)[1]));
599: printf ("}\n");
600: }
601:
602: /* Process a define_expand just read. Assign its code number,
603: only for the purposes of `insn_gen_function'. */
604:
605: void
606: gen_expand (insn)
607: rtx insn;
608: {
609: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
610: register int i;
611:
612: d->code_number = next_code_number++;
613: if (XSTR (insn, 0)[0])
614: d->name = XSTR (insn, 0);
615: else
616: d->name = 0;
617:
618: /* Build up the list in the same order as the insns are seen
619: in the machine description. */
620: d->next = 0;
621: if (end_of_insn_data)
622: end_of_insn_data->next = d;
623: else
624: insn_data = d;
625:
626: end_of_insn_data = d;
627:
628: max_opno = -1;
629: num_dups = 0;
630:
631: /* Scan the operands to get the specified predicates and modes,
632: since expand_binop needs to know them. */
633:
634: mybzero (predicates, sizeof predicates);
635: mybzero (modes, sizeof modes);
636: if (XVEC (insn, 1))
637: for (i = 0; i < XVECLEN (insn, 1); i++)
638: scan_operands (XVECEXP (insn, 1, i), 0, 0);
639: d->n_operands = max_opno + 1;
640: mybcopy (predicates, d->predicates, sizeof predicates);
641: mybcopy (modes, d->modes, sizeof modes);
642:
643: mybzero (d->constraints, sizeof constraints);
1.1.1.5 ! root 644: mybzero (d->op_n_alternatives, sizeof op_n_alternatives);
1.1.1.2 root 645: mybzero (d->address_p, sizeof address_p);
646: mybzero (d->strict_low, sizeof strict_low);
647:
648: d->n_dups = 0;
649: d->template = 0;
650: d->outfun = 0;
1.1.1.4 root 651: d->machine_info = 0;
1.1.1.2 root 652: }
653:
654: int
1.1 root 655: xmalloc (size)
656: {
657: register int val = malloc (size);
658:
659: if (val == 0)
1.1.1.2 root 660: fatal ("virtual memory exhausted");
1.1 root 661: return val;
662: }
663:
664: int
665: xrealloc (ptr, size)
666: char *ptr;
667: int size;
668: {
669: int result = realloc (ptr, size);
670: if (!result)
1.1.1.2 root 671: fatal ("virtual memory exhausted");
1.1 root 672: return result;
673: }
674:
675: void
1.1.1.2 root 676: mybzero (b, length)
677: register char *b;
678: register int length;
679: {
680: while (length-- > 0)
681: *b++ = 0;
682: }
683:
684: void
685: mybcopy (b1, b2, length)
686: register char *b1;
687: register char *b2;
688: register int length;
689: {
690: while (length-- > 0)
691: *b2++ = *b1++;
692: }
693:
694: void
1.1 root 695: fatal (s, a1, a2)
696: {
1.1.1.2 root 697: fprintf (stderr, "genoutput: ");
1.1 root 698: fprintf (stderr, s, a1, a2);
699: fprintf (stderr, "\n");
1.1.1.2 root 700: exit (FATAL_EXIT_CODE);
1.1 root 701: }
702:
1.1.1.2 root 703: int
1.1 root 704: main (argc, argv)
705: int argc;
706: char **argv;
707: {
708: rtx desc;
709: FILE *infile;
710: extern rtx read_rtx ();
711: register int c;
712:
1.1.1.2 root 713: obstack_init (rtl_obstack);
1.1 root 714:
715: if (argc <= 1)
716: fatal ("No input file name.");
717:
718: infile = fopen (argv[1], "r");
719: if (infile == 0)
720: {
721: perror (argv[1]);
1.1.1.2 root 722: exit (FATAL_EXIT_CODE);
1.1 root 723: }
724:
725: init_rtl ();
726:
727: output_prologue ();
728: next_code_number = 0;
729: have_constraints = 0;
730:
731: /* Read the machine description. */
732:
733: while (1)
734: {
735: c = read_skip_spaces (infile);
736: if (c == EOF)
737: break;
738: ungetc (c, infile);
739:
740: desc = read_rtx (infile);
1.1.1.2 root 741: if (GET_CODE (desc) == DEFINE_INSN)
742: gen_insn (desc);
743: if (GET_CODE (desc) == DEFINE_PEEPHOLE)
744: gen_peephole (desc);
745: if (GET_CODE (desc) == DEFINE_EXPAND)
746: gen_expand (desc);
1.1 root 747: }
748:
749: output_epilogue ();
750:
1.1.1.2 root 751: fflush (stdout);
752: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
1.1 root 753: }
1.1.1.5 ! root 754:
! 755: int
! 756: n_occurrences (c, s)
! 757: char c;
! 758: char *s;
! 759: {
! 760: int n = 0;
! 761: while (*s)
! 762: n += (*s++ == c);
! 763: return n;
! 764: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.