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