]> gcc.gnu.org Git - gcc.git/blame - gcc/genemit.c
c-parse.in (language_string): Constify.
[gcc.git] / gcc / genemit.c
CommitLineData
65963943 1/* Generate code from machine description to emit insns as rtl.
34627ce6 2 Copyright (C) 1987, 88, 91, 94, 95, 97, 98, 1999 Free Software Foundation, Inc.
65963943
RK
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
a35311b0
RK
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
65963943
RK
20
21
0d64891c 22#include "hconfig.h"
0b93b64e 23#include "system.h"
65963943
RK
24#include "rtl.h"
25#include "obstack.h"
f8b6598e 26#include "errors.h"
65963943
RK
27
28static struct obstack obstack;
29struct obstack *rtl_obstack = &obstack;
30
31#define obstack_chunk_alloc xmalloc
32#define obstack_chunk_free free
33
4db83042
MM
34/* Define this so we can link with print-rtl.o to get debug_rtx function. */
35char **insn_name_ptr = 0;
36
65963943
RK
37static int max_opno;
38static int max_dup_opno;
39static int register_constraints;
40static int insn_code_number;
41static int insn_index_number;
42
43/* Data structure for recording the patterns of insns that have CLOBBERs.
44 We use this to output a function that adds these CLOBBERs to a
45 previously-allocated PARALLEL expression. */
46
47struct clobber_pat
48{
e5f6a288 49 struct clobber_ent *insns;
65963943
RK
50 rtx pattern;
51 int first_clobber;
52 struct clobber_pat *next;
53} *clobber_list;
54
e5f6a288
RK
55/* Records one insn that uses the clobber list. */
56
57struct clobber_ent
58{
59 int code_number; /* Counts only insns. */
60 struct clobber_ent *next;
61};
62
e009aaf3
JL
63static void max_operand_1 PROTO((rtx));
64static int max_operand_vec PROTO((rtx, int));
65static void print_code PROTO((RTX_CODE));
66static void gen_exp PROTO((rtx));
67static void gen_insn PROTO((rtx));
68static void gen_expand PROTO((rtx));
69static void gen_split PROTO((rtx));
70static void output_add_clobbers PROTO((void));
71static void output_init_mov_optab PROTO((void));
72
73\f
65963943
RK
74static void
75max_operand_1 (x)
76 rtx x;
77{
78 register RTX_CODE code;
79 register int i;
80 register int len;
6f7d635c 81 register const char *fmt;
65963943
RK
82
83 if (x == 0)
84 return;
85
86 code = GET_CODE (x);
87
88 if (code == MATCH_OPERAND && XSTR (x, 2) != 0 && *XSTR (x, 2) != '\0')
89 register_constraints = 1;
90 if (code == MATCH_SCRATCH && XSTR (x, 1) != 0 && *XSTR (x, 1) != '\0')
91 register_constraints = 1;
92 if (code == MATCH_OPERAND || code == MATCH_OPERATOR
93 || code == MATCH_PARALLEL)
94 max_opno = MAX (max_opno, XINT (x, 0));
8fabbfe6 95 if (code == MATCH_DUP || code == MATCH_OP_DUP || code == MATCH_PAR_DUP)
65963943
RK
96 max_dup_opno = MAX (max_dup_opno, XINT (x, 0));
97
98 fmt = GET_RTX_FORMAT (code);
99 len = GET_RTX_LENGTH (code);
100 for (i = 0; i < len; i++)
101 {
102 if (fmt[i] == 'e' || fmt[i] == 'u')
103 max_operand_1 (XEXP (x, i));
104 else if (fmt[i] == 'E')
105 {
106 int j;
107 for (j = 0; j < XVECLEN (x, i); j++)
108 max_operand_1 (XVECEXP (x, i, j));
109 }
110 }
111}
112
113static int
114max_operand_vec (insn, arg)
115 rtx insn;
116 int arg;
117{
118 register int len = XVECLEN (insn, arg);
119 register int i;
120
121 max_opno = -1;
122 max_dup_opno = -1;
123
124 for (i = 0; i < len; i++)
125 max_operand_1 (XVECEXP (insn, arg, i));
126
127 return max_opno + 1;
128}
129\f
130static void
131print_code (code)
132 RTX_CODE code;
133{
5f06c983 134 register const char *p1;
65963943
RK
135 for (p1 = GET_RTX_NAME (code); *p1; p1++)
136 {
137 if (*p1 >= 'a' && *p1 <= 'z')
138 putchar (*p1 + 'A' - 'a');
139 else
140 putchar (*p1);
141 }
142}
143
144/* Print a C expression to construct an RTX just like X,
145 substituting any operand references appearing within. */
146
147static void
148gen_exp (x)
149 rtx x;
150{
151 register RTX_CODE code;
152 register int i;
153 register int len;
6f7d635c 154 register const char *fmt;
65963943
RK
155
156 if (x == 0)
157 {
3d678dca 158 printf ("NULL_RTX");
65963943
RK
159 return;
160 }
161
162 code = GET_CODE (x);
163
164 switch (code)
165 {
166 case MATCH_OPERAND:
167 case MATCH_DUP:
168 printf ("operand%d", XINT (x, 0));
169 return;
170
171 case MATCH_OP_DUP:
4ceb7595
JC
172 printf ("gen_rtx (GET_CODE (operand%d), ", XINT (x, 0));
173 if (GET_MODE (x) == VOIDmode)
174 printf ("GET_MODE (operand%d)", XINT (x, 0));
175 else
176 printf ("%smode", GET_MODE_NAME (GET_MODE (x)));
65963943
RK
177 for (i = 0; i < XVECLEN (x, 1); i++)
178 {
179 printf (",\n\t\t");
180 gen_exp (XVECEXP (x, 1, i));
181 }
182 printf (")");
183 return;
184
185 case MATCH_OPERATOR:
186 printf ("gen_rtx (GET_CODE (operand%d)", XINT (x, 0));
187 printf (", %smode", GET_MODE_NAME (GET_MODE (x)));
188 for (i = 0; i < XVECLEN (x, 2); i++)
189 {
190 printf (",\n\t\t");
191 gen_exp (XVECEXP (x, 2, i));
192 }
193 printf (")");
194 return;
195
196 case MATCH_PARALLEL:
8fabbfe6 197 case MATCH_PAR_DUP:
65963943
RK
198 printf ("operand%d", XINT (x, 0));
199 return;
200
201 case MATCH_SCRATCH:
3b80f6ca 202 printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x)));
65963943
RK
203 return;
204
205 case ADDRESS:
206 fatal ("ADDRESS expression code used in named instruction pattern");
207
208 case PC:
209 printf ("pc_rtx");
210 return;
211
212 case CC0:
213 printf ("cc0_rtx");
214 return;
215
216 case CONST_INT:
217 if (INTVAL (x) == 0)
3d678dca
RS
218 printf ("const0_rtx");
219 else if (INTVAL (x) == 1)
220 printf ("const1_rtx");
221 else if (INTVAL (x) == -1)
222 printf ("constm1_rtx");
223 else if (INTVAL (x) == STORE_FLAG_VALUE)
224 printf ("const_true_rtx");
225 else
76d31c63
JL
226 {
227 printf ("GEN_INT (");
228 printf (HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
229 printf (")");
230 }
3d678dca
RS
231 return;
232
233 case CONST_DOUBLE:
234 /* These shouldn't be written in MD files. Instead, the appropriate
235 routines in varasm.c should be called. */
236 abort ();
1d300e19
KG
237
238 default:
239 break;
65963943
RK
240 }
241
3b80f6ca 242 printf ("gen_rtx_");
65963943 243 print_code (code);
3b80f6ca 244 printf (" (%smode", GET_MODE_NAME (GET_MODE (x)));
65963943
RK
245
246 fmt = GET_RTX_FORMAT (code);
247 len = GET_RTX_LENGTH (code);
248 for (i = 0; i < len; i++)
249 {
250 if (fmt[i] == '0')
251 break;
a558d864 252 printf (",\n\t");
65963943
RK
253 if (fmt[i] == 'e' || fmt[i] == 'u')
254 gen_exp (XEXP (x, i));
255 else if (fmt[i] == 'i')
3d678dca 256 printf ("%u", XINT (x, i));
65963943
RK
257 else if (fmt[i] == 's')
258 printf ("\"%s\"", XSTR (x, i));
259 else if (fmt[i] == 'E')
260 {
261 int j;
262 printf ("gen_rtvec (%d", XVECLEN (x, i));
263 for (j = 0; j < XVECLEN (x, i); j++)
264 {
265 printf (",\n\t\t");
266 gen_exp (XVECEXP (x, i, j));
267 }
268 printf (")");
269 }
270 else
271 abort ();
272 }
273 printf (")");
274}
275\f
276/* Generate the `gen_...' function for a DEFINE_INSN. */
277
278static void
279gen_insn (insn)
280 rtx insn;
281{
282 int operands;
283 register int i;
284
285 /* See if the pattern for this insn ends with a group of CLOBBERs of (hard)
286 registers or MATCH_SCRATCHes. If so, store away the information for
0f41302f 287 later. */
65963943
RK
288
289 if (XVEC (insn, 1))
290 {
291 for (i = XVECLEN (insn, 1) - 1; i > 0; i--)
292 if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER
293 || (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != REG
294 && GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH))
295 break;
296
297 if (i != XVECLEN (insn, 1) - 1)
298 {
e5f6a288
RK
299 register struct clobber_pat *p;
300 register struct clobber_ent *link
301 = (struct clobber_ent *) xmalloc (sizeof (struct clobber_ent));
302 register int j;
303
304 link->code_number = insn_code_number;
305
306 /* See if any previous CLOBBER_LIST entry is the same as this
307 one. */
308
309 for (p = clobber_list; p; p = p->next)
310 {
311 if (p->first_clobber != i + 1
312 || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1))
313 continue;
314
315 for (j = i + 1; j < XVECLEN (insn, 1); j++)
316 {
317 rtx old = XEXP (XVECEXP (p->pattern, 1, j), 0);
318 rtx new = XEXP (XVECEXP (insn, 1, j), 0);
319
320 /* OLD and NEW are the same if both are to be a SCRATCH
f5f178e0 321 of the same mode,
e5f6a288 322 or if both are registers of the same mode and number. */
f5f178e0
RS
323 if (! (GET_MODE (old) == GET_MODE (new)
324 && ((GET_CODE (old) == MATCH_SCRATCH
325 && GET_CODE (new) == MATCH_SCRATCH)
326 || (GET_CODE (old) == REG && GET_CODE (new) == REG
327 && REGNO (old) == REGNO (new)))))
e5f6a288
RK
328 break;
329 }
330
331 if (j == XVECLEN (insn, 1))
332 break;
333 }
334
335 if (p == 0)
336 {
337 p = (struct clobber_pat *) xmalloc (sizeof (struct clobber_pat));
65963943 338
e5f6a288
RK
339 p->insns = 0;
340 p->pattern = insn;
341 p->first_clobber = i + 1;
342 p->next = clobber_list;
343 clobber_list = p;
344 }
345
346 link->next = p->insns;
347 p->insns = link;
65963943
RK
348 }
349 }
350
6b6ca844
RK
351 /* Don't mention instructions whose names are the null string
352 or begin with '*'. They are in the machine description just
353 to be recognized. */
354 if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*')
65963943
RK
355 return;
356
357 /* Find out how many operands this function has,
358 and also whether any of them have register constraints. */
359 register_constraints = 0;
360 operands = max_operand_vec (insn, 1);
361 if (max_dup_opno >= operands)
362 fatal ("match_dup operand number has no match_operand");
363
364 /* Output the function name and argument declarations. */
365 printf ("rtx\ngen_%s (", XSTR (insn, 0));
366 for (i = 0; i < operands; i++)
367 printf (i ? ", operand%d" : "operand%d", i);
368 printf (")\n");
369 for (i = 0; i < operands; i++)
370 printf (" rtx operand%d;\n", i);
371 printf ("{\n");
372
373 /* Output code to construct and return the rtl for the instruction body */
374
375 if (XVECLEN (insn, 1) == 1)
376 {
377 printf (" return ");
378 gen_exp (XVECEXP (insn, 1, 0));
379 printf (";\n}\n\n");
380 }
381 else
382 {
3b80f6ca 383 printf (" return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (%d", XVECLEN (insn, 1));
65963943
RK
384 for (i = 0; i < XVECLEN (insn, 1); i++)
385 {
386 printf (",\n\t\t");
387 gen_exp (XVECEXP (insn, 1, i));
388 }
389 printf ("));\n}\n\n");
390 }
391}
392\f
393/* Generate the `gen_...' function for a DEFINE_EXPAND. */
394
395static void
396gen_expand (expand)
397 rtx expand;
398{
399 int operands;
400 register int i;
401
402 if (strlen (XSTR (expand, 0)) == 0)
403 fatal ("define_expand lacks a name");
404 if (XVEC (expand, 1) == 0)
405 fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0));
406
407 /* Find out how many operands this function has,
408 and also whether any of them have register constraints. */
409 register_constraints = 0;
410
411 operands = max_operand_vec (expand, 1);
412
413 /* Output the function name and argument declarations. */
414 printf ("rtx\ngen_%s (", XSTR (expand, 0));
415 for (i = 0; i < operands; i++)
416 printf (i ? ", operand%d" : "operand%d", i);
417 printf (")\n");
418 for (i = 0; i < operands; i++)
419 printf (" rtx operand%d;\n", i);
420 printf ("{\n");
421
422 /* If we don't have any C code to write, only one insn is being written,
423 and no MATCH_DUPs are present, we can just return the desired insn
424 like we do for a DEFINE_INSN. This saves memory. */
425 if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0')
426 && operands > max_dup_opno
427 && XVECLEN (expand, 1) == 1)
428 {
429 printf (" return ");
430 gen_exp (XVECEXP (expand, 1, 0));
431 printf (";\n}\n\n");
432 return;
433 }
434
435 /* For each operand referred to only with MATCH_DUPs,
436 make a local variable. */
437 for (i = operands; i <= max_dup_opno; i++)
438 printf (" rtx operand%d;\n", i);
439 if (operands > 0 || max_dup_opno >= 0)
440 printf (" rtx operands[%d];\n", MAX (operands, max_dup_opno + 1));
441 printf (" rtx _val = 0;\n");
442 printf (" start_sequence ();\n");
443
444 /* The fourth operand of DEFINE_EXPAND is some code to be executed
445 before the actual construction.
446 This code expects to refer to `operands'
447 just as the output-code in a DEFINE_INSN does,
448 but here `operands' is an automatic array.
449 So copy the operand values there before executing it. */
450 if (XSTR (expand, 3) && *XSTR (expand, 3))
451 {
452 /* Output code to copy the arguments into `operands'. */
453 for (i = 0; i < operands; i++)
454 printf (" operands[%d] = operand%d;\n", i, i);
455
456 /* Output the special code to be executed before the sequence
457 is generated. */
458 printf ("%s\n", XSTR (expand, 3));
459
460 /* Output code to copy the arguments back out of `operands'
461 (unless we aren't going to use them at all). */
462 if (XVEC (expand, 1) != 0)
463 {
464 for (i = 0; i < operands; i++)
465 printf (" operand%d = operands[%d];\n", i, i);
466 for (; i <= max_dup_opno; i++)
467 printf (" operand%d = operands[%d];\n", i, i);
468 }
469 }
470
471 /* Output code to construct the rtl for the instruction bodies.
472 Use emit_insn to add them to the sequence being accumulated.
473 But don't do this if the user's code has set `no_more' nonzero. */
474
475 for (i = 0; i < XVECLEN (expand, 1); i++)
476 {
477 rtx next = XVECEXP (expand, 1, i);
478 if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
479 || (GET_CODE (next) == PARALLEL
480 && GET_CODE (XVECEXP (next, 0, 0)) == SET
481 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
482 || GET_CODE (next) == RETURN)
483 printf (" emit_jump_insn (");
484 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
485 || GET_CODE (next) == CALL
486 || (GET_CODE (next) == PARALLEL
487 && GET_CODE (XVECEXP (next, 0, 0)) == SET
488 && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
489 || (GET_CODE (next) == PARALLEL
490 && GET_CODE (XVECEXP (next, 0, 0)) == CALL))
491 printf (" emit_call_insn (");
492 else if (GET_CODE (next) == CODE_LABEL)
493 printf (" emit_label (");
494 else if (GET_CODE (next) == MATCH_OPERAND
d3ca5cdd 495 || GET_CODE (next) == MATCH_DUP
65963943 496 || GET_CODE (next) == MATCH_OPERATOR
65963943 497 || GET_CODE (next) == MATCH_OP_DUP
d3ca5cdd
JW
498 || GET_CODE (next) == MATCH_PARALLEL
499 || GET_CODE (next) == MATCH_PAR_DUP
65963943
RK
500 || GET_CODE (next) == PARALLEL)
501 printf (" emit (");
502 else
503 printf (" emit_insn (");
504 gen_exp (next);
505 printf (");\n");
506 if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
507 && GET_CODE (SET_SRC (next)) == LABEL_REF)
508 printf (" emit_barrier ();");
509 }
510
511 /* Call `gen_sequence' to make a SEQUENCE out of all the
512 insns emitted within this gen_... function. */
513
65963943 514 printf (" _val = gen_sequence ();\n");
65963943
RK
515 printf (" end_sequence ();\n");
516 printf (" return _val;\n}\n\n");
517}
518
519/* Like gen_expand, but generates a SEQUENCE. */
0f41302f 520
65963943
RK
521static void
522gen_split (split)
523 rtx split;
524{
525 register int i;
526 int operands;
527
528 if (XVEC (split, 0) == 0)
3462dc45 529 fatal ("define_split (definition %d) lacks a pattern", insn_index_number);
65963943 530 else if (XVEC (split, 2) == 0)
3462dc45
RK
531 fatal ("define_split (definition %d) lacks a replacement pattern",
532 insn_index_number);
65963943
RK
533
534 /* Find out how many operands this function has. */
535
536 max_operand_vec (split, 2);
537 operands = MAX (max_opno, max_dup_opno) + 1;
538
69277eec
KG
539 /* Output the prototype, the function name and argument declarations. */
540 printf ("extern rtx gen_split_%d PROTO ((rtx *));\n", insn_code_number);
65963943
RK
541 printf ("rtx\ngen_split_%d (operands)\n rtx *operands;\n",
542 insn_code_number);
543 printf ("{\n");
544
545 /* Declare all local variables. */
546 for (i = 0; i < operands; i++)
547 printf (" rtx operand%d;\n", i);
91afd8f5 548 printf (" rtx _val = 0;\n");
65963943
RK
549 printf (" start_sequence ();\n");
550
551 /* The fourth operand of DEFINE_SPLIT is some code to be executed
552 before the actual construction. */
553
554 if (XSTR (split, 3))
555 printf ("%s\n", XSTR (split, 3));
556
557 /* Output code to copy the arguments back out of `operands' */
558 for (i = 0; i < operands; i++)
559 printf (" operand%d = operands[%d];\n", i, i);
560
561 /* Output code to construct the rtl for the instruction bodies.
562 Use emit_insn to add them to the sequence being accumulated.
563 But don't do this if the user's code has set `no_more' nonzero. */
564
565 for (i = 0; i < XVECLEN (split, 2); i++)
566 {
567 rtx next = XVECEXP (split, 2, i);
568 if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
569 || (GET_CODE (next) == PARALLEL
570 && GET_CODE (XVECEXP (next, 0, 0)) == SET
571 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
572 || GET_CODE (next) == RETURN)
573 printf (" emit_jump_insn (");
574 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
575 || GET_CODE (next) == CALL
576 || (GET_CODE (next) == PARALLEL
577 && GET_CODE (XVECEXP (next, 0, 0)) == SET
578 && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
579 || (GET_CODE (next) == PARALLEL
580 && GET_CODE (XVECEXP (next, 0, 0)) == CALL))
581 printf (" emit_call_insn (");
582 else if (GET_CODE (next) == CODE_LABEL)
583 printf (" emit_label (");
584 else if (GET_CODE (next) == MATCH_OPERAND
585 || GET_CODE (next) == MATCH_OPERATOR
586 || GET_CODE (next) == MATCH_PARALLEL
587 || GET_CODE (next) == MATCH_OP_DUP
588 || GET_CODE (next) == MATCH_DUP
589 || GET_CODE (next) == PARALLEL)
590 printf (" emit (");
591 else
592 printf (" emit_insn (");
593 gen_exp (next);
594 printf (");\n");
595 if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
596 && GET_CODE (SET_SRC (next)) == LABEL_REF)
597 printf (" emit_barrier ();");
598 }
599
600 /* Call `gen_sequence' to make a SEQUENCE out of all the
601 insns emitted within this gen_... function. */
602
65963943 603 printf (" _val = gen_sequence ();\n");
65963943
RK
604 printf (" end_sequence ();\n");
605 printf (" return _val;\n}\n\n");
606}
607\f
608/* Write a function, `add_clobbers', that is given a PARALLEL of sufficient
609 size for the insn and an INSN_CODE, and inserts the required CLOBBERs at
610 the end of the vector. */
611
612static void
613output_add_clobbers ()
614{
615 struct clobber_pat *clobber;
e5f6a288 616 struct clobber_ent *ent;
65963943
RK
617 int i;
618
619 printf ("\n\nvoid\nadd_clobbers (pattern, insn_code_number)\n");
620 printf (" rtx pattern;\n int insn_code_number;\n");
621 printf ("{\n");
65963943
RK
622 printf (" switch (insn_code_number)\n");
623 printf (" {\n");
624
625 for (clobber = clobber_list; clobber; clobber = clobber->next)
626 {
e5f6a288
RK
627 for (ent = clobber->insns; ent; ent = ent->next)
628 printf (" case %d:\n", ent->code_number);
65963943
RK
629
630 for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++)
631 {
632 printf (" XVECEXP (pattern, 0, %d) = ", i);
633 gen_exp (XVECEXP (clobber->pattern, 1, i));
634 printf (";\n");
635 }
636
e5f6a288 637 printf (" break;\n\n");
65963943
RK
638 }
639
640 printf (" default:\n");
641 printf (" abort ();\n");
642 printf (" }\n");
643 printf ("}\n");
644}
645\f
2778b98d 646PTR
65963943 647xmalloc (size)
2778b98d 648 size_t size;
65963943 649{
2778b98d 650 register PTR val = (PTR) malloc (size);
65963943
RK
651
652 if (val == 0)
653 fatal ("virtual memory exhausted");
654
655 return val;
656}
657
2778b98d 658PTR
470b68c0
RH
659xrealloc (old, size)
660 PTR old;
2778b98d 661 size_t size;
65963943 662{
470b68c0 663 register PTR ptr;
09d83d25 664 if (old)
470b68c0
RH
665 ptr = (PTR) realloc (old, size);
666 else
667 ptr = (PTR) malloc (size);
668 if (!ptr)
65963943 669 fatal ("virtual memory exhausted");
470b68c0 670 return ptr;
65963943
RK
671}
672
65963943
RK
673int
674main (argc, argv)
675 int argc;
676 char **argv;
677{
678 rtx desc;
679 FILE *infile;
65963943
RK
680 register int c;
681
f8b6598e 682 progname = "genemit";
65963943
RK
683 obstack_init (rtl_obstack);
684
685 if (argc <= 1)
686 fatal ("No input file name.");
687
688 infile = fopen (argv[1], "r");
689 if (infile == 0)
690 {
691 perror (argv[1]);
692 exit (FATAL_EXIT_CODE);
693 }
694
65963943
RK
695 /* Assign sequential codes to all entries in the machine description
696 in parallel with the tables in insn-output.c. */
697
698 insn_code_number = 0;
699 insn_index_number = 0;
700
701 printf ("/* Generated automatically by the program `genemit'\n\
702from the machine description file `md'. */\n\n");
703
704 printf ("#include \"config.h\"\n");
729da3f5 705 printf ("#include \"system.h\"\n");
65963943 706 printf ("#include \"rtl.h\"\n");
49ad7cfa 707 printf ("#include \"function.h\"\n");
65963943
RK
708 printf ("#include \"expr.h\"\n");
709 printf ("#include \"real.h\"\n");
1d300e19 710 printf ("#include \"flags.h\"\n");
65963943 711 printf ("#include \"output.h\"\n");
7f7f8214
KG
712 printf ("#include \"insn-config.h\"\n");
713 printf ("#include \"insn-flags.h\"\n");
714 printf ("#include \"insn-codes.h\"\n");
715 printf ("#include \"recog.h\"\n");
716 printf ("#include \"reload.h\"\n\n");
65963943
RK
717 printf ("extern rtx recog_operand[];\n");
718 printf ("#define operands emit_operand\n\n");
53bfe9cd
JC
719 printf ("#define FAIL return (end_sequence (), _val)\n");
720 printf ("#define DONE return (_val = gen_sequence (), end_sequence (), _val)\n");
65963943
RK
721
722 /* Read the machine description. */
723
724 while (1)
725 {
726 c = read_skip_spaces (infile);
727 if (c == EOF)
728 break;
729 ungetc (c, infile);
730
731 desc = read_rtx (infile);
732 if (GET_CODE (desc) == DEFINE_INSN)
733 {
734 gen_insn (desc);
735 ++insn_code_number;
736 }
737 if (GET_CODE (desc) == DEFINE_EXPAND)
738 {
739 gen_expand (desc);
740 ++insn_code_number;
741 }
742 if (GET_CODE (desc) == DEFINE_SPLIT)
743 {
744 gen_split (desc);
745 ++insn_code_number;
746 }
747 if (GET_CODE (desc) == DEFINE_PEEPHOLE)
748 {
749 ++insn_code_number;
750 }
751 ++insn_index_number;
752 }
753
754 /* Write out the routine to add CLOBBERs to a pattern. */
755 output_add_clobbers ();
756
65963943
RK
757 fflush (stdout);
758 exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
759 /* NOTREACHED */
760 return 0;
761}
This page took 0.704188 seconds and 5 git commands to generate.